Snippets / Accessibility /

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.

Button with forced-colors support
Input with HCM-safe focus ring
Widely Supported
a11yno-js

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.