CSSHigh Contrast & forced-colors

High Contrast & forced-colors

Some users configure their operating system to override every page's colors with a small, high-contrast palette they control — Windows High Contrast Mode is the most common example. When this is active, the browser ignores most of your custom colors entirely and substitutes system-level colors instead. Many developers have never tested their site this way, which means color-dependent UI often breaks silently for exactly the users who most need it to work.

Detecting forced-colors mode

The forced-colors media feature tells you when this restricted palette is active, so you can adjust layout or add elements (like borders) that the forced palette alone won't give you.

CSS
@media (forced-colors: active) {
  .card {
    /* Borders often survive forced-colors better than shadows or
       subtle background differences — add one explicitly to preserve
       the visual grouping the card conveyed before. */
    border: 1px solid CanvasText;
  }
}
System color keywords

Inside forced-colors mode, the OS defines a small set of named colors that map to its current high-contrast theme. Using these keywords — rather than your normal palette — means your UI adapts correctly to whatever theme the user has chosen (which might be black-on-white, white-on-black, or a custom combination).

Keyword

Typical use

CanvasText

Default body text color

Canvas

Default page background

LinkText

Unvisited link color

VisitedText

Visited link color

ButtonFace

Default background of button-like controls

ButtonText

Text color on button-like controls

Highlight

Background of selected/highlighted content

HighlightText

Text color on selected/highlighted content

CSS
@media (forced-colors: active) {
  .btn--primary {
    background: ButtonFace;
    color: ButtonText;
    border: 1px solid ButtonText;
  }

  a {
    color: LinkText;
  }

  .selected-row {
    background: Highlight;
    color: HighlightText;
  }
}
Warning
Under forced colors, the browser typically flattens backgrounds, removes background images, and can make subtle effects like box-shadow-based borders or low-contrast background images invisible or confusing — a card that relied purely on a faint shadow to separate itself from the page can visually merge into its background entirely. Anything communicated only through a background image, gradient, or shadow needs a forced-colors fallback (typically a real border) or it silently disappears for these users.
Opting an element out

Occasionally an element genuinely needs its own colors even in forced-colors mode (a brand logo, for instance). The forced-color-adjust property lets you exempt specific elements, but it should be used sparingly — most content benefits from following the user's chosen high-contrast palette.

CSS
.brand-logo {
  forced-color-adjust: none; /* keep this element's own colors intact */
}
Note
Testing in forced-colors mode is a genuine, low-effort accessibility QA step: on Windows, enabling High Contrast mode (via Settings → Accessibility) and clicking through your site for a few minutes reliably surfaces UI that silently breaks for users who rely on it every day.
Next
Pair this with baseline contrast checks on [Color Contrast & Readability](/css/color-contrast), and with theme architecture on [Dark Mode](/css/dark-mode) and [CSS Theming with Custom Properties](/css/css-theming).