|
| 1 | +--- |
| 2 | +title: "Forced colours mode" |
| 3 | +slug: forced-colors |
| 4 | +category: accessibility |
| 5 | +summary: "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." |
| 6 | +status: recommended |
| 7 | +order: 15 |
| 8 | +appliesTo: [all] |
| 9 | +relatedSlugs: [color-contrast, color-scheme, reduced-motion] |
| 10 | +updated: "2026-06-22T00:00:00.000Z" |
| 11 | +sources: |
| 12 | + - title: "CSS Media Queries Level 5 — forced-colors" |
| 13 | + url: "https://drafts.csswg.org/mediaqueries-5/#forced-colors" |
| 14 | + publisher: "W3C" |
| 15 | + - title: "CSS Color Adjustment Module Level 1 — forced-color-adjust" |
| 16 | + url: "https://drafts.csswg.org/css-color-adjust-1/#forced" |
| 17 | + publisher: "W3C" |
| 18 | + - title: "MDN — forced-colors" |
| 19 | + url: "https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/forced-colors" |
| 20 | + publisher: "MDN" |
| 21 | +--- |
| 22 | + |
| 23 | +## What it is |
| 24 | + |
| 25 | +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. |
| 26 | + |
| 27 | +```css |
| 28 | +@media (forced-colors: active) { |
| 29 | + .card { |
| 30 | + /* box-shadow is forced to none — restore the boundary with a border */ |
| 31 | + border: 1px solid CanvasText; |
| 32 | + } |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +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`. |
| 37 | + |
| 38 | +## Why it matters |
| 39 | + |
| 40 | +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. |
| 41 | + |
| 42 | +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. |
| 43 | + |
| 44 | +## How to implement |
| 45 | + |
| 46 | +- **Build on semantic HTML.** Real `<button>`, `<a>`, and form controls map to system colour keywords automatically; custom `<div>` widgets do not. |
| 47 | +- **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. |
| 48 | +- **Restore lost boundaries.** Where a control or container was defined by `box-shadow` or background colour alone, add a `border` or `outline` inside `@media (forced-colors: active)`. |
| 49 | +- **Opt out sparingly.** `forced-color-adjust: none` on 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. |
| 50 | +- **Pair with `prefers-contrast: more`** for users who asked for higher contrast without a forced palette — the two queries serve different audiences. |
| 51 | + |
| 52 | +The site ships forced-colours-aware styles; see the related [colour contrast](/spec/accessibility/color-contrast/) page. |
| 53 | + |
| 54 | +## Common mistakes |
| 55 | + |
| 56 | +- Hard-coding colours inside the query instead of using system colour keywords, re-breaking the user's palette. |
| 57 | +- Conveying state (selected, error, disabled) through colour that forced mode discards, with no border, icon, or text fallback. |
| 58 | +- Slapping `forced-color-adjust: none` across large regions, defeating the mode for everything inside. |
| 59 | +- Using the deprecated `-ms-high-contrast` media query instead of standard `forced-colors`. |
| 60 | + |
| 61 | +## Verification |
| 62 | + |
| 63 | +- On Windows, enable **Settings → Accessibility → Contrast themes** and pick a theme; reload the page. |
| 64 | +- In Chrome or Edge DevTools, open the Rendering panel and set **Emulate CSS media feature forced-colors: active**. |
| 65 | +- Confirm every control and container keeps a visible boundary, and that no state is signalled by colour alone. |
0 commit comments