Skip to content
GreenSnippets

Dark mode with CSS custom properties and color-scheme

Switch themes by redefining variables under prefers-color-scheme, with a manual override attribute.

CSS
:root {
  color-scheme: light dark;
  --bg: #fafaf7;
  --fg: #16181a;
  --accent: #15803d;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0b0d0c;
    --fg: #ecefed;
    --accent: #2ee55a;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0b0d0c;
  --fg: #ecefed;
  --accent: #2ee55a;
}

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

How it works

Define colors once as custom properties and override them for dark mode. color-scheme tells the browser to render built-in controls and scrollbars in the matching theme. The [data-theme] selectors let a toggle override the OS preference; the :not([data-theme="light"]) guard keeps an explicit light choice from being overridden by a dark OS.

Check contrast in both themes (WCAG AA is 4.5:1 for body text).

This snippet has been reviewed but was not executed by an automated test. Test it in your own environment before relying on it.