Back to blog

Designing Flawless Dark & Light Modes with CSS

A step-by-step playbook for shipping polished theme toggles that respect user preference and stay accessible.

Desk lit with both cool and warm lighting to represent theme switching.
Photo by Stephanie Krist on Unsplash

Dark mode is no longer an optional theme—it is a core part of brand perception and accessibility. The key is to lead with semantics: define tokens, respect user preferences, and avoid one-off overrides when something feels misaligned.

  • Start with design tokens mapped to CSS custom properties
  • Honor prefers-color-scheme for first render
  • Use a toggle that persists intent with localStorage
  • Audit contrast for both themes before shipping
:root {
  color-scheme: light dark;
  --surface: #ffffff;
  --surface-inset: #f4f6fb;
  --text: #1f2933;
  --accent: #274690;
}

@media (prefers-color-scheme: dark) {
  :root {
    --surface: #101623;
    --surface-inset: #151d2d;
    --text: #f5f7fa;
    --accent: #5c8bff;
  }
}

body.theme--dark {
  --surface: #101623;
  --surface-inset: #151d2d;
  --text: #f5f7fa;
  --accent: #5c8bff;
}

By layering the system preference with a user-controlled toggle, you offer a flawless experience whether someone opens the page at noon or midnight.