High Contrast Mode
Use @media (forced-colors: active) and system color keywords to keep buttons, inputs, and focus rings usable when Windows High Contrast Mode overrides your palette.
Quick implementation
/* Default styles work normally in all browsers */
.btn {
background: var(--accent-bg);
color: oklch(1 0 0);
border: 2px solid transparent;
border-radius: 0.375rem;
padding: 0.6rem 1.25rem;
}
.btn:focus-visible {
outline: 3px solid var(--accent);
outline-offset: 3px;
}
/* When Windows High Contrast Mode is active,
the OS overrides most CSS colors.
Map to system color keywords so the button
remains visually distinct. */
@media (forced-colors: active) {
.btn {
background: ButtonFace;
color: ButtonText;
border-color: ButtonText; /* gives the button a visible edge */
forced-color-adjust: none; /* opt out of automatic remapping */
}
.btn:focus-visible {
outline-color: Highlight; /* system highlight color */
}
}
/* System color keywords available in forced-colors:
Canvas, CanvasText, ButtonFace, ButtonText,
Highlight, HighlightText, GrayText, LinkText */Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are an accessibility-focused CSS developer. Implement forced-colors support for a design system.
Requirements:
1. Write default CSS for a .btn component with a custom accent background and white text.
2. Add @media (forced-colors: active) overrides that use system color keywords: ButtonFace, ButtonText, Highlight, Canvas, CanvasText.
3. Add forced-color-adjust: none to components where you want to control the HCM rendering yourself rather than letting the browser auto-remap.
4. Show how to ensure focus rings remain visible in HCM — use outline: 3px solid Highlight.
5. Handle a custom checkbox or toggle — these often break in HCM because background-based indicators get wiped out. Use border or outline instead.
Constraints:
- Do NOT use -ms-high-contrast — it is deprecated. Use forced-colors: active instead.
- System keywords are case-sensitive in some parsers — use exact casing: ButtonFace, ButtonText, Canvas, CanvasText, Highlight, HighlightText, GrayText, LinkText.
- forced-color-adjust: none should be used sparingly — it prevents the OS from protecting contrast.
Output CSS + brief explanation of each system color keyword's semantic meaning.Why this matters in 2026
Windows High Contrast Mode is used by an estimated 1–2% of Windows users — typically people with low vision, migraines, or cognitive disabilities who need extreme contrast to use a screen at all. When HCM is active, the OS overrides nearly all custom CSS colors, replacing them with a minimal system palette. Without forced-colors support, buttons can become invisible, focus rings disappear, and custom checkboxes break entirely. The fix is straightforward: add a single @media block that maps your UI to semantic system colors.
The logic
@media (forced-colors: active) fires whenever the user has enabled a high-contrast color scheme at the OS level. Inside this block, use CSS System Color Keywords — ButtonFace, ButtonText, Canvas, CanvasText, Highlight — to give elements semantic meaning rather than hardcoded values. The OS then renders each keyword in the user's chosen high-contrast palette. forced-color-adjust: none opts a specific element out of automatic remapping, allowing you to apply the system colors yourself manually.
Accessibility & performance
Testing is straightforward: enable High Contrast Mode in Windows Settings → Accessibility → Contrast Themes, or emulate it in Chrome DevTools under Rendering → Emulate CSS media feature forced-colors. Focus on interactive elements first — buttons, links, inputs, custom controls. Decorative backgrounds and illustrations are handled automatically by the OS. There is no performance cost: forced-colors overrides are applied at the style cascade level, equivalent to any other media query branch.