The Trouble With Picking Black or White Text

Andy Clarke recently put his finger on a real limitation of the CSS contrast-color() function. For his own site, he deliberately chose an off-white text color (#d3d5da) against a dark blue background (#212E45) to soften the harshness of pure white while still meeting accessibility targets. The problem? When contrast-color() evaluates that background, it will always hand back solid white or solid black—never a softer intermediate tone.

When Maximum Contrast Isn't Ideal

White and black are guaranteed to provide the strongest possible contrast against any other color. But "most contrast" does not necessarily mean "best contrast" for reading comfort. That was exactly the issue when adding a dark color scheme to a personal site: the jump between the deep blue background (hsl(238.2 53.1% 12.5%)) and pure #fff text felt visually jarring.

For those cases, the author wanted something less opaque than solid white—a value like hsl(100 100% 100% / .8), or a tone roughly 20% lighter than white. The contrast-color() function simply cannot express that. This is one reason to reach for the light-dark() function instead, which allows explicit, custom color pairs:

body {
  color: light-dark(hsl(238.2 53.1% 12.5%), hsl(100 100% 100% / .8));
}

Room to Grow in the Spec

The good news is that the CSS specification acknowledges this limitation. On the future of contrast-color(), the spec states:

Future versions of this specification are expected to introduce more control over both the contrast algorithm(s) used, the use cases, as well as the returned color.

Getting that right is easier said than done. The "correct" amount of contrast is not simply a fixed ratio like 4.5:1—it also depends on individual user preferences. Making contrast-color() smarter will require navigating the same tricky territory that ongoing WCAG 3.0 work is exploring, as Danny recently outlined in a deeper look at the shortcomings of contrast-color().