Home / Articles / Color & Theming /
prefers-color-scheme: auto-detecting dark mode
Respect the user's system setting. Dark mode in CSS, no JavaScript toggle required.
Why system preference matters
Every major operating system — macOS, Windows, iOS, Android — has a dark mode toggle. Users expect websites to follow that preference. A site that blasts bright white at midnight ignores a signal the user has already set. prefers-color-scheme reads that OS-level preference directly in CSS.
The basic pattern
Define your light-mode tokens as defaults, then override them in a dark-mode media query:
:root {
--bg: oklch(0.97 0.006 260);
--text: oklch(0.18 0.025 260);
--card: oklch(1 0 0);
--border: oklch(0 0 0 / 0.07);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: oklch(0.13 0.02 260);
--text: oklch(0.93 0.01 260);
--card: oklch(0.19 0.02 260);
--border: oklch(1 0 0 / 0.07);
}
}
Every component that uses these tokens automatically adapts. You write the dark mode override once, in one place.
The light-dark() function
CSS now has a dedicated function for this pattern. Instead of a media query, you can write both values inline:
:root {
color-scheme: light dark;
}
body {
background: light-dark(oklch(0.97 0.006 260), oklch(0.13 0.02 260));
color: light-dark(oklch(0.18 0.025 260), oklch(0.93 0.01 260));
}
.card {
background: light-dark(oklch(1 0 0), oklch(0.19 0.02 260));
border: 1px solid light-dark(oklch(0 0 0 / 0.07), oklch(1 0 0 / 0.07));
}
The color-scheme: light dark declaration tells the browser to use the OS preference to choose which value light-dark() returns. This is more concise than media queries for simple value swaps.
Images and shadows in dark mode
Colors adapt via tokens, but images and shadows need separate attention. Bright images can be jarring in dark mode. Use filter: brightness(0.85) on images in dark contexts, or provide alternate image sources with <picture>. Shadows should be more opaque in dark mode — oklch(0 0 0 / 0.3) instead of oklch(0 0 0 / 0.1) — because they need more contrast against dark backgrounds.
Browser support
prefers-color-scheme is supported in Chrome 76+, Safari 12.1+, and Firefox 67+. The light-dark() function is supported in Chrome 123+, Safari 17.5+, and Firefox 120+. In 2026, both are Baseline Widely Available.
prefers-color-scheme media query for maximum browser support. Switch to light-dark() for new projects targeting 2025+ browsers.