Adjust Text Color to Match Background Contrast
Mix text color toward black or white based on the background to maintain WCAG contrast. Combine color-mix() with light-dark() for full theme awareness.
Detailed Explanation
Deriving Readable Text Colors
When a background color is dynamic (user-themed, data-driven, randomly
generated), the foreground text color also has to adapt. color-mix()
gives you a clean expression for that adaptation:
.chip {
background: var(--bg-color);
color: color-mix(in oklch, var(--bg-color), white 92%);
}
This produces text that lives in the same hue family as the background but is pulled most of the way toward white — typically enough contrast for body copy on a mid-tone background.
A more robust pattern: light-dark()
For real production use, combine with the new light-dark() function:
.chip {
background: var(--bg-color);
color: light-dark(
color-mix(in oklch, var(--bg-color), black 92%),
color-mix(in oklch, var(--bg-color), white 92%)
);
}
Now the text picks black-on-light in light mode and white-on-dark in dark mode automatically.
Verify with WCAG
color-mix() does not check contrast for you. Always run candidate
foreground/background pairs through the
accessibility color checker and
target at least 4.5:1 for body text and 3:1 for large/UI text.
Limits
For arbitrary hue backgrounds you may still need a deliberate
high-contrast text token (--text-on-brand: #fff). Use color-mix()
for derived UI surfaces and reserve hardcoded text-on-color tokens for
brand-critical pairs.
Use Case
User-generated themes, data-driven chips/badges, color-coded calendars, and any UI where the background is decided at runtime and the text must remain readable.