may 16, 2026
🔗 Contrast-proofing colors
Previously in Text selection color, I covered how the most important thing to keep in mind when setting custom highlight colors, is keeping the contrast high enough. Until recently this meant picking a colour, running it through a checker, and revisiting it whenever the brand palette changed.
In 2026 the contrast-color() function reached baseline support, and the browser can now handle this part directly.
::selection,
::target-text,
::search-text {
background: yellow;
color: black;
color: contrast-color(yellow);
}
The function returns black or white, depending on which value has the greatest contrast with the input color. When the background colour changes, the text follows, removing one manual step from the design system.
# Uses
This new function can have its place in a couple of scenarios.
- Light/dark themes. No manual changes for handling both light and dark themes. Just reference a CSS variable that changes with the dark/light theming and the function will output which text color works best.
:root {
--primary-color: light-dark(#333b3c, #efefec);
}
::selection {
background: var(--primary-color);
color: contrast-color(var(--primary-color));
}
- Customizable background-colors. Imagine you have a piece of UI, for example an announcement bar above the header, which the site owner can customise its background color from the CMS. After all, they might use their brand color, but occasionally switch to orange during the Halloween sales. In this case
contrast-color()can offer some safety for the site owner to always have a readable result.
<div
class="ticker bg-(--bg-color) text-[contrast-color(var(--bg-color))]"
style="--bg-color: {{ data.background_color }};"
>
# Doesn't compose with color-mix()
Nesting inside a color-mix() could be a nice idea. While the brand color is a solid color, the selection color could use a semi-transperent version of the same hue. But unfortunately that doesn't work today:
background-color: color-mix(in oklab, var(--color-primary) 10%, transparent);
color: contrast-color(color-mix(in oklab, var(--color-primary) 10%, transparent));
# Accessibility disclaimer
The MDN docs are explicit about the limits of WCAG AA as the basis for the algorithm:
Warning: WCAG AA (4.5:1) contrast is not capable of producing clearly readable text in all cases. Mid-tone background colors generally don't provide enough contrast with either black or white foreground. For example, contrast-color() on a royal bluish (#2277d3) background produces black text, which is not readable for small text. It is recommended, therefore, to use light or dark colors with the contrast-color() function.
In practice, contrast-color() is best suited to colours that already sit clearly at one end of the lightness scale. Mid-tones still need a manual judgement call.