Sam Hooke

Pure CSS dark mode support

It is easy to support dark mode with pure CSS. No JavaScript required.

Just define your light and dark theme colours using CSS variables near the top of your stylesheet:

style.css §
:root {
  /* Inform browser both light and dark themes are supported. */
  color-scheme: light dark;

  /* Light theme. */
  --col-primary: #123123;
  --col-secondary: #67676e;
  --col-text-main: #333;
  --col-text-subtle: #c2c1c4;
  --col-bg-main: #fefefe;
  --col-bg-series: #efeff0;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Dark theme. */
    --col-primary: #9757e4;
    --col-secondary: #9483aa;
    --col-text-main: #bdbdbd;
    --col-text-subtle: #78747b;
    --col-bg-main: #2a2d2c;
    --col-bg-series: #48454c;
  }

  img {
    /* Make images dimmer for dark theme. */
    filter: brightness(85%);
  }
}

This ties dark mode into the browser and/or OS settings. The light theme variables are not wrapped within a @media block, and so will be used by default. The dark theme variables are wrapped within @media (prefers-color-scheme: dark) { ... }, and so will be used only if the user has dark mode enabled in the browser/OS.

If you want a button on the web page for toggling light/dark mode, then you will need to use JavaScript. Personally I’m happy to just rely upon browser/OS settings.

Use of the color-scheme property is not strictly necessary, but is intended to inform the browser that the element can be “comfortably”1 be rendered in the given colour schemes.

Update the rest of your stylesheet to use these variables for all colours:2

style.css (everywhere else) §
main {
  background-color: var(--col-bg-main);
  color: var(--col-text-main);
  /* ... */
}

Then in your HTML header, include this line3:

<meta name="color-scheme" content="light dark">

That’s it!

Switching between light and dark mode §

To switch between light and dark mode, use your browser and/or OS settings, e.g.:

  • In Windows 10, go to Windows Settings → Personalisation → Colours → Choose your colour, and switch between Light and Dark.
  • In Firefox, go to Menu → Settings (or about:preferences), then under General scroll down to Language and Appearance. By default, Automatic is selected, which will use the OS setting. To override this, select Light or Dark.

  1. The word “comfortably” is used both by MDN and web.dev. That’s putting a lot of trust in the website developers to provide “comfortable” themes! ↩︎

  2. The MDN example shows defining each element twice, one wrapped in @media (prefers-color-scheme: light) { ... } and another in @media (prefers-color-scheme: dark) { ... }. I find it simpler to just have one @media query for the two sets of variables, and then define each element just once using the variables. Though interestingly, it does note there is an experimental light-dark() function, which might offer a simpler alternative in future. ↩︎

  3. Again, the color-scheme meta tag is not strictly necessary, but helps “user agents in rendering the page background with the desired color scheme immediately”. ↩︎