In web development, forced colors mode is a browser-level setting which replaces websites’ colors (backgrounds, borders, text, focus outlines, and more) with a significantly reduced color palette, sometimes comprised of user-selected colors. Forced colors mode also makes changes which simplify an interface’s appearance, such as removing elements’ box shadows.
Low-vision users might find forced colors mode useful for setting all webpages in a high-contrast palette. Meanwhile, people with migraines might use forced colors mode to set a muted, less stimulating, low-contrast palette. The fact that some people prefer to set lower-contrast themes is why accessibility practitioners, browsers, and operating systems have moved away from calling these features “high-contrast mode” over the past few years.
In some cases, users will access forced colors mode through their browser’s settings. In other cases, the user enables forced colors mode at the operating system level. On Windows, for instance, they could enable contrast themes, formerly known as Windows High Contrast Mode (WHCM). Other operating systems (I’m at least aware of Ubuntu and Android) have similar functionality. After enabling the OS-wide setting, the browser will pick it up and apply it to webpages automatically.
Styling for Forced Colors Mode
CSS allows developers to modify how a webpage appears in forced colors mode. When doing so, remember that the goal is to add clarity where it might have been lost, not to try to force your own aesthetic preferences or branding.
To check if forced colors mode is enabled, use a forced-colors
media query:
@media (forced-colors: active) {
/* Forced colors mode is enabled */
}
@media (forced-colors: none) {
/* Forced colors mode is not currently enabled */
}
In some limited cases, the exact original color of an element really matters, such as product swatches or chart legends. In this case, you can use the forced-color-adjust
property to opt a particular element out of forced colors mode styling:
/* Default. Element will take on forced colors mode styles. */
forced-color-adjust: auto;
/* Element will not take on forced colors mode styles. */
forced-color-adjust: none;
/* Used to enable `currentColor` (or similar) in contexts such as SVGs */
forced-color-adjust: preserve-parent-color;
System Colors
When forced colors mode is active, elements’ colors are remapped to system colors, named color variables whose values have been set at the browser or operating system level. Other defined colors, such as those set with hex codes, color functions, or the transparent
keyword, will generally be ignored by default (save for messing with forced-color-adjust
).
As of January 2025, the CSS Color Module Level 4 draft spec defines these system colors:
AccentColor
andAccentColorText
, for accented user interface controlsActiveText
, for the text in active links (links that are currently being pressed)ButtonBorder
,ButtonFace
, andButtonText
for buttonsCanvas
andCanvasText
, for document defaults (the standard page background and default, noninteractive text)Field
andFieldText
, for inputsGrayText
, for disabled text (despite the name, won’t necessarily end up gray)Highlight
andHighlightText
, for text selectionsLinkText
, for hyperlinksMark
andMarkText
for text highlighted through, for instance, the<mark>
tagSelectedItem
andSelectedItemText
, for selected controls such as checkboxes or radio buttonsVisitedText
, for hyperlinks to visited destinations
Some of these colors are defined in pairs/
By default, semantic HTML elements will be mapped to the appropriate system colors. In these cases, you shouldn’t even need to mess with system colors at all. These system color keywords will really only come in handy whenever you’re creating more custom widgets. When possible, try to stick to the system colors that most closely match the intended meaning or functionality of your component, to make sure your UI is as predictable as possible. For example, if you’re creating a custom button, use the button-specific system color keywords.
Deprecated Styles for Windows High Contrast Mode
These “-ms
”-prefixed proprietary properties or keywords targeted the former Windows High Contrast Mode specifically, and have since been deprecated in favor of the standardized forced colors mode properties:
- The
-ms-high-contrast
media feature, which was used to detect whether Windows High Contrast Mode was enabled. Use aforced-colors
media query instead. - The
-ms-high-contrast-adjust
property, which was used to opt an element out of Windows High Contrast Mode styling. Useforced-color-adjust
instead.
At this point, you should probably only be using these WHCM-specific styles if you still need to support Internet Explorer and even still, you should include them alongside today’s standardized forced colors styles.
External Resources
- Forced colors explained: A practical guide, by Kilian Valkhof for the Polypane blog
- Styling for Windows high contrast with new standards for forced colors, on the Microsoft Edge blog
- Windows High Contrast Mode, Forced Colors Mode And CSS Custom Properties, by Eric Bailey for Smashing Magazine