Using CSS prefers-contrast for High-Contrast Needs

The CSS prefers-contrast media query detects whether a user has requested an interface with heightened or diminished contrast through their operating system settings. This article explains how the media feature functions, details its available values, and demonstrates practical CSS techniques to adapt colors, borders, and typography to meet high-contrast accessibility requirements.

Understanding prefers-contrast

Part of the CSS Media Queries Level 5 specification, prefers-contrast queries the user's system preferences to adjust the visual presentation of a website automatically. This is critical for users with low vision, color blindness, or situational impairments (such as viewing a screen in direct sunlight).

The media feature supports four primary values:

  • no-preference: The user has not expressed a preference. This serves as the default state.
  • more: The user prefers a higher level of contrast between elements and backgrounds.
  • less: The user prefers a lower level of contrast, often to reduce eye strain or migraine triggers.
  • custom: The user has enabled a specific, restricted palette (such as Windows High Contrast Mode) where forced colors are applied.

Adapting Styles for High-Contrast Needs

When users request higher contrast (prefers-contrast: more), subtle design patterns—like faint borders, soft shadows, low-contrast text, or pastel backgrounds—can become unreadable. Developers use this query to deliver a sharper, clearer interface.

1. Boosting Text and Background Contrast

Websites often use off-blacks, grays, and muted tones for secondary text. In high-contrast mode, these should be adjusted to achieve maximum contrast ratios.

/* Default styles */
body {
  background-color: #f9f9f9;
  color: #555555;
}

/* High-contrast adaptation */
@media (prefers-contrast: more) {
  body {
    background-color: #ffffff;
    color: #000000;
  }
}

2. Enhancing Interactive Elements and Borders

Modern UI design frequently relies on subtle drop shadows (box-shadow) to differentiate cards, inputs, and buttons. For users needing high contrast, distinct solid borders are much more perceptible.

.card {
  background: #ffffff;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

@media (prefers-contrast: more) {
  .card {
    box-shadow: none;
    border: 2px solid #000000;
  }
}

3. Strengthening Focus States and Outlines

Standard focus rings can blend into complex backgrounds. Enhancing the focus outline when prefers-contrast: more is active ensures users navigating via keyboard can easily track their position.

button:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

@media (prefers-contrast: more) {
  button:focus-visible {
    outline: 3px solid #000000;
    outline-offset: 3px;
  }
}

4. Removing Decorative Noise

Subtle gradients, background patterns, and semi-transparent overlays can reduce readability. Inside the high-contrast query, flatten these elements into solid, opaque colors to keep the foreground text legible.

.hero-banner {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
}

@media (prefers-contrast: more) {
  .hero-banner {
    background: #00008b; /* Solid dark blue */
    color: #ffffff;
  }
}

prefers-contrast vs. forced-colors

It is important to differentiate prefers-contrast from the forced-colors media query. While forced-colors signals that the operating system has restricted the palette to a limited system set (overriding author colors automatically), prefers-contrast: more allows the developer to intentionally refine their own design palette to ensure compliance, maintain visual hierarchy, and provide an accessible experience tailored to the user's needs.