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.
@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 |
@media (forced-colors: active) {
.btn--primary {
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
}
a {
color: LinkText;
}
.selected-row {
background: Highlight;
color: HighlightText;
}
}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.
.brand-logo {
forced-color-adjust: none; /* keep this element's own colors intact */
}