Skip to content

add guide body for contrast-color#966

Open
patrickkettner wants to merge 1 commit into
mainfrom
contrast-color-guide
Open

add guide body for contrast-color#966
patrickkettner wants to merge 1 commit into
mainfrom
contrast-color-guide

Conversation

@patrickkettner

Copy link
Copy Markdown
Contributor

Follow-up to #753, which merged contrast-color as a stub (step 1: frontmatter + demo.html). This adds the full guide.md body.

Restores the guidance written earlier and incorporates the use cases @jamesnw suggested in the #753 review:

  • Derive readable hover/interaction states — change only the background custom property via relative color syntax and let contrast-color() re-derive the foreground (algorithmic hover states).
  • Build colors beyond black and white — feed the contrast-color() result into relative color syntax, with an explicit accessibility caveat that the contrast guarantee no longer holds once the value is transformed.

Use cases: optimal text color, custom-property theming, hover/interaction states, derived colors, plus fallback strategy.

Refs #687

@jamesnw jamesnw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good! I have a few suggestions, and I think the demo will need to be updated to more closely match the guide.

I think we should also add notes that caution against using contrast-color() over gradients, images, or backgrounds with transparency.


# Ensure text readability with dynamic background colors

When building reusable UI components (like badges or buttons) or supporting dynamic themes, ensuring text is readable against an unpredictable background color can be challenging. The `contrast-color()` CSS function automatically selects either black or white to maximize the contrast ratio against a specified background color.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When building reusable UI components (like badges or buttons) or supporting dynamic themes, ensuring text is readable against an unpredictable background color can be challenging. The `contrast-color()` CSS function automatically selects either black or white to maximize the contrast ratio against a specified background color.
When building reusable UI components (like badges or buttons) or supporting dynamic themes, ensuring text is readable against an unpredictable background color can be challenging. The `contrast-color()` CSS function resolves to `black` or `white`, maximizing the contrast ratio against the specified background color.

Comment on lines +11 to +12

This guide explains how to use `contrast-color()` to guarantee text legibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This guide explains how to use `contrast-color()` to guarantee text legibility.

I don't think this is needed.


When an element has a variable or dynamically injected background color, you can rely on the browser to compute the safest text color.

MANDATORY: You must define a fallback strategy for older browsers, such as using an `@supports` query with a `text-shadow` or variant-specific colors, because a single static fallback color will inevitably fail against some dynamic backgrounds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to talk about fallbacks in the main section of the guide


MANDATORY: You must define a fallback strategy for older browsers, such as using an `@supports` query with a `text-shadow` or variant-specific colors, because a single static fallback color will inevitably fail against some dynamic backgrounds.

MANDATORY: Set the `color` property using the `contrast-color()` function, passing the effective background color (or its custom property) as the argument.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what's meant by "effective" here- I think it can be removed?

}
```

DO: Use `contrast-color()` primarily when backgrounds are distinctly light or dark. Because the function currently only selects between black or white, mid-tone backgrounds (such as royal blue) may result in suboptimal contrast even when the mathematical maximum is chosen.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than mid-tone, would it make sense to say lightness specifically?

@supports (color: contrast-color(red)) {
.button:hover {
/* Darken the background; the text color re-derives on its own */
--button-bg: oklch(from #4f46e5 calc(l - 0.1) c h);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to make this example actually flip the text from white to black- this should do it.

Suggested change
--button-bg: oklch(from #4f46e5 calc(l - 0.1) c h);
--button-bg: oklch(from #4f46e5 calc(1 - l) c h);


## Fallback strategies

{{ FEATURE_FALLBACKS("contrast-color") }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{{ FEATURE_FALLBACKS("contrast-color") }}
{{ BASELINE_STATUS("contrast-color") }}


{{ FEATURE_FALLBACKS("contrast-color") }}

Due to its limited availability, `contrast-color()` must be applied using progressive enhancement. If the background color is known and fixed for a specific CSS class (like a `.badge-dark` variant), declaring a variant-specific safe default `color` immediately before the `contrast-color()` rule is sufficient, because browsers ignore CSS values they do not understand.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the prose needs to talk about availability.

Suggested change
Due to its limited availability, `contrast-color()` must be applied using progressive enhancement. If the background color is known and fixed for a specific CSS class (like a `.badge-dark` variant), declaring a variant-specific safe default `color` immediately before the `contrast-color()` rule is sufficient, because browsers ignore CSS values they do not understand.
For browsers that do not yet support `contrast-color()`, use it as a progressive enhancement. If the background color is known and fixed for a specific CSS class (like a `.badge-dark` variant), declare a variant-specific safe default `color` immediately before the `contrast-color()` rule.


Due to its limited availability, `contrast-color()` must be applied using progressive enhancement. If the background color is known and fixed for a specific CSS class (like a `.badge-dark` variant), declaring a variant-specific safe default `color` immediately before the `contrast-color()` rule is sufficient, because browsers ignore CSS values they do not understand.

However, if the background color is highly dynamic and unpredictable (such as user-injected themes), a single static fallback will inevitably fail. In these cases, you MUST use an `@supports` feature query to apply a robust fallback strategy, such as a text shadow or translucent background, to guarantee readability.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also mention using a library like ColorJS to compute a contrast color in JavaScript.

Another option would be using RCS, but that isn't widely available yet. Perhaps we don't need to mention that. https://lea.verou.me/blog/2024/contrast-color/#using-rcs-to-automatically-compute-a-contrasting-text-color

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants