Implementing Dark Mode with CSS prefers-color-scheme

Respecting a user’s OS-level dark mode preference is now a single media query away — no JavaScript, no cookie, no flash of the wrong theme on load.

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

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #121212;
        --text: #e0e0e0;
        --card-bg: #1e1e1e;
    }
}

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

Letting Users Override the OS Preference

/* A manual toggle needs to override the media query with a class,
   set via a small bit of JavaScript that stores the preference */
:root[data-theme="dark"] {
    --bg: #121212;
    --text: #e0e0e0;
}

Combine both: default to prefers-color-scheme for users who haven’t chosen, but let a manual toggle set an explicit data-theme attribute that takes precedence — this is exactly the pattern most well-built dark mode toggles use today.