Forced colours mode
Respect forced colours mode (Windows High Contrast and similar). The `forced-colors` media feature lets you repair UI the user's palette would otherwise flatten — without overriding their choice.
What it is
Some users override every site’s colours with a small, high-contrast palette of their own. Windows High Contrast mode is the best-known example; the operating system or browser substitutes the user’s chosen foreground, background, link, and button colours for whatever the page declared. The browser exposes that state through the forced-colors media feature, which is active when a forced palette is in effect.
@media (forced-colors: active) {
.card {
/* box-shadow is forced to none — restore the boundary with a border */
border: 1px solid CanvasText;
}
}
Forced colours mode works automatically for most semantic markup. The feature exists for the cases where the substitution removes information — and for the rare element that should opt out via forced-color-adjust.
Why it matters
The high contrast of a reduced palette is essential for some users with low vision, light sensitivity, or cognitive needs to read a page at all. When forced colours apply, the browser drops box-shadow, flattens background images behind text, and recolours borders and text to system colours. UI that relied on a shadow, a background-colour swatch, or a coloured-but-borderless control can lose its visible boundary entirely.
Respecting the mode means two things: never fighting the user’s palette, and repairing the few places where their palette erases a distinction your design carried in colour alone.
How to implement
- Build on semantic HTML. Real
<button>,<a>, and form controls map to system colour keywords automatically; custom<div>widgets do not. - Use CSS system colours inside the query —
CanvasText,Canvas,LinkText,ButtonText,ButtonFace,Highlight— so repairs track the user’s actual palette rather than hard-coded values. - Restore lost boundaries. Where a control or container was defined by
box-shadowor background colour alone, add aborderoroutlineinside@media (forced-colors: active). - Opt out sparingly.
forced-color-adjust: noneon an element (e.g. a colour-picker swatch or a meaningful chart key) preserves its own colours. Use it only where the colour is the information. - Pair with
prefers-contrast: morefor users who asked for higher contrast without a forced palette — the two queries serve different audiences.
The site ships forced-colours-aware styles; see the related colour contrast page.
Common mistakes
- Hard-coding colours inside the query instead of using system colour keywords, re-breaking the user’s palette.
- Conveying state (selected, error, disabled) through colour that forced mode discards, with no border, icon, or text fallback.
- Slapping
forced-color-adjust: noneacross large regions, defeating the mode for everything inside. - Using the deprecated
-ms-high-contrastmedia query instead of standardforced-colors.
Verification
- On Windows, enable Settings → Accessibility → Contrast themes and pick a theme; reload the page.
- In Chrome or Edge DevTools, open the Rendering panel and set Emulate CSS media feature forced-colors: active.
- Confirm every control and container keeps a visible boundary, and that no state is signalled by colour alone.