TechLead

Accessibility and User Preferences

Focus styles, contrast, and system settings

CSS media features let you adapt your design to user system preferences — dark mode, reduced motion, high contrast, and more. Respecting these preferences is both an accessibility requirement and good UX: users who need them rely on them for usability or health reasons.

prefers-color-scheme — Dark Mode

Detects whether the user has chosen a dark or light system theme. Implement dark mode with CSS custom properties so the entire theme flips with a single media query.

:root {
  --color-bg:   #ffffff;
  --color-text: #1a1a1a;
  --color-card: #f5f5f5;
  --color-border: #e0e0e0;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg:   #0f172a;
    --color-text: #e2e8f0;
    --color-card: #1e293b;
    --color-border: #334155;
  }
}

body {
  background: var(--color-bg);
  color: var(--color-text);
}

Allowing User Override with JavaScript

Many sites allow users to override the system preference with a toggle. Store the preference and apply a class that overrides the media query.

// Apply saved preference on load
const saved = localStorage.getItem('theme');
if (saved) document.documentElement.dataset.theme = saved;

// Toggle button
function toggleTheme() {
  const current = document.documentElement.dataset.theme;
  const next = current === 'dark' ? 'light' : 'dark';
  document.documentElement.dataset.theme = next;
  localStorage.setItem('theme', next);
}
/* Override via data attribute */
[data-theme="dark"]  { --color-bg: #0f172a; --color-text: #e2e8f0; }
[data-theme="light"] { --color-bg: #ffffff; --color-text: #1a1a1a; }

prefers-reduced-motion — Reducing Animations

Users with vestibular disorders, epilepsy, or attention sensitivities may request reduced motion. Parallax, large auto-playing animations, and spinning loaders can trigger discomfort. This media feature is the most safety-critical of the preference queries.

/* Provide animations by default */
.card {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}

/* Remove or simplify when the user prefers reduced motion */
@media (prefers-reduced-motion: reduce) {
  .card {
    transition: none;
  }
  .card:hover {
    transform: none;
  }

  /* Stop all auto-playing animations */
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

prefers-contrast — High Contrast

Some users require higher contrast ratios than your default design provides. prefers-contrast: more is supported in Safari and Chrome; use it to increase border widths, remove low-contrast shadows, and boost text contrast.

@media (prefers-contrast: more) {
  :root {
    --color-text: #000000;
    --color-bg: #ffffff;
    --color-border: #000000;
  }

  .button {
    border: 2px solid currentColor;
    box-shadow: none;
  }

  .placeholder {
    color: #595959; /* meets 4.5:1 against white */
  }
}

/* Windows High Contrast Mode (Edge/IE) */
@media (forced-colors: active) {
  .button {
    border: 2px solid ButtonText;
    color: ButtonText;
    background: ButtonFace;
  }
}

prefers-reduced-data

An emerging feature that lets you serve lighter assets when the user is on a metered or slow connection.

@media (prefers-reduced-data: reduce) {
  /* Skip decorative background images */
  .hero { background-image: none; }

  /* Load lower-quality images via CSS */
  img { image-rendering: auto; }
}

Best Practices

  • Treat prefers-reduced-motion: reduce as a hard requirement, not a suggestion
  • Use CSS custom properties for theming — they make media-query overrides a single block
  • Test with your OS set to dark mode and reduced motion enabled, not just in DevTools
  • Ensure colour contrast meets WCAG AA (4.5:1 for normal text) in both light and dark themes
  • Never use !important to fight user stylesheets — honour forced-colors mode instead

Continue Learning