CSS forced-colors media query for Windows High Contrast

Windows High Contrast support without broken UI

Windows High Contrast and similar forced-color modes ignore most of your CSS. Custom backgrounds vanish, drop shadows disappear, and decorative borders get stripped. forced-colors lets you opt back in with system colors that the OS guarantees will be readable.

Old way no fallback
/* no forced-colors handling: in High Contrast mode the background is stripped   and the transparent border becomes invisible. The button disappears. */.btn   {  background: var(--accent);  color: white;  border: 1px solid transparent;}
system colors
.btn   {  background: var(--accent);  color: white;  border: 1px solid transparent;}@media (forced-colors: active)   {  .btn {    background: ButtonFace;    color: ButtonText;    border: 1px solid ButtonText;    forced-color-adjust: none;  }}/* High Contrast users see a real button instead of a coloured rectangle */
Widely available Since 2022 95% global usage

This feature is well established and works across many devices and browser versions. It has been available across browsers since 2022.

Safe to use without fallbacks.

89+
89+
16+
79+
simulated forced-colors mode. The unfixed button has no visible edge.
no forced-colors handling
background and border stripped, text left
@media (forced-colors: active)
explicit border + system color pair
simulation only. Real forced-colors uses your OS High Contrast palette.

Buttons stay buttons

In forced-colors mode the OS strips backgrounds and shadows. Without an opt-in, the button you styled with a coloured background and no border becomes invisible. ButtonFace and ButtonText guarantee the OS will render them with a readable contrast pair.

Pairs with prefers-contrast

Use @media (prefers-contrast: more) for users who asked for higher contrast but are not in forced-colors mode. The two queries cover different audiences. Stack them when both matter.

Opt out of overrides

forced-color-adjust: none tells the browser "trust me, I have already adapted these colours". Use it sparingly and only after you have confirmed the contrast still works.

Key Change
OS-driven palette
System colors guarantee contrast
Old Approach
no fallback
Buttons disappear in High Contrast
Modern Approach
@media (forced-colors: active)
Opt in with system colors

How it works

Windows High Contrast (now called Contrast Themes) and similar modes on other platforms force a small palette of OS-defined colours onto every page. The browser strips most background images, drop shadows, and custom borders. If your button relied on a coloured background with no visible border, it becomes a transparent rectangle.

The fix is two queries used together. @media (forced-colors: active) fires only when the OS is in a forced-colors mode. Inside it, set the colours that matter using system color keywords like ButtonFace, ButtonText, LinkText, Highlight, and HighlightText. These map to whatever palette the user picked, so you do not need to know in advance which colours they want.

forced-color-adjust: none opts a specific element out of the OS overrides. Reach for it only when you have already paired the foreground and background using system colours, otherwise you are taking responsibility for accessibility the browser was handling for you.

ESC