Kilian Valkhof

Building tools that make developers awesome.

I no longer understand prefers-contrast

CSS & HTML, 8 March 2023, 3 minute read

The prefers-contrast media query indicates whether someone prefers more or less contrast within the boundaries of your sites design. At least, that’s what I thought it meant, and it’s also how macOS seems to implement it with their ‘increase contrast’ accessibility feature. This is in contrast to the forced-colors media query, which overwrites all your styles.

To me it was clear that they served different purposes: one was to indicate a preference for an implemented design, just with more (or less) contrast, the other wanted 100% certainty that their colors were respected. Clear difference, clear implementation.

Except that turned out to be wrong.

While macOS sees prefers-contrast as a discrete thing, the spec (and Windows) intricately links it to forced-colors. There, prefers-contrast:more matches when forced-colors with a high contrast theme is active, and prefers-contrast: custom is active with a contrast theme that has anything other than a full black or white background.

So now I’m left wondering: What on earth do spec makers expect website builders to do with prefers-contrast? If forced-colors already overwrites all the colors, what contrast is there left for us to change?

prefers-contrast is a useless media query, and I don't understand why.

This isn’t the first time I’ve voiced concerns about prefers-contrast: earlier versions of the spec had a forced value that would match only when forced-colors was active. I thought this was a really dumb idea, wrote about it and to my surprise, the forced value got removed from the spec. Victory!

…Except they put it back as custom and apparently retooled the entire media query to match with forced-colors: active.

Worse still, the spec only mentions this in the forced-colors section, while the prefers contrast section only mentions prefers-contrast: custom matching when forced-colors: active matches. Under forced colors however, this is what the latest version of the spec says:

In addition to forced-colors: active, the user agent must also match one of prefers-contrast: more or prefers-contrast: less if it can determine that the forced color palette chosen by the user has a particularly high or low contrast, and must make prefers-contrast: custom match otherwise.
Similarly, if the forced color palette chosen by the user fits within one of the color schemes described by prefers-color-scheme, the corresponding value must also match.

Contrast this to what the version before it said:

The UA will provide the color palette to authors through the CSS system color keywords and, if appropriate, trigger the appropriate value of prefers-color-scheme so that authors can adapt the page.

That's a whole new section essentially fusing prefers-contrast to forced-colors.

Coupling forced-colors and prefers-contrast like this completely breaks the ‘contract’ that the prefers-* prefix gives: a user has preference and it’s up to you to implement it. This is in contrast to other media queries, like width and, indeed, forced-colors, that tell us that something is a more intrinsic state of the device being used to access your site.

Prefers-* in media queries is no longer something you can depend upon, and CSS is a little bit less explainable and a little less consistent.

Why do this?

I have no idea why they decided this was a good idea. Maybe the spec makers are confused by the name of ‘contrast themes’ on Windows and decided that contrast is contrast and no further research was needed?

I also have no any idea what to do with prefers contrast. It exists, and there is literally no reason to use it on its own.

This is doubly annoying for macOS, which has a very clear implementation for prefers-contrast: more. If you want to adapt your design for macOS, you can no longer use just that. You need to check if prefers-contrast: more is active, and if forced-colors isn’t:

@media (prefer-contrast: more) and (forced-colors: none) {
    /* Only now can you apply styling for the macOS implementation */
}

No one is going to do that, and the spec makers know this because "adoption being low" is a common argument made by the CSS working group against any new media queries (like prefers-reduced-complexity, which is also tacked onto prefers-contrast by using it without a value). Usage being low is a great way to stop any discussion dead in the water, and is far from consistently applied throughout the specs being written.

So that leaves me with this: I no longer understand prefers-contrast. I can’t explain why you would use it, I don’t know who it’s for or what developers are expected to do with it. Do you?

Polypane browser for responsive web development and design Hi, I'm Kilian. I make Polypane, the browser for responsive web development and design. If you're reading this site, that's probably interesting to you. Try it out!