current theme: placeholder

The modern way to implement CSS light/dark themes

Published on

Before

The common way to implement a CSS light/dark theme toggle is to declare your default theme custom properties at the root and change these values with a .dark (or similar) class:

:root {
  --body-background-color: white;
  --text-color: black;
}

:root.dark {
  --body-background-color: black;
  --text-color: white;
}

Now

Now that the color-scheme CSS property and the light-dark() CSS function are available in modern browsers, there is a much cleaner way to set this up that removes duplication and makes it easier to read and maintain.

:root {
  color-scheme: light dark;

  --body-background-color: light-dark(white, black);
  --text-color: light-dark(black, white);
}

:root.dark {
  color-scheme: dark;
}

In practice today, the useful keywords are light and dark. The <custom-ident> listed on MDN is there for forward compatibility in the specs:

<custom-ident> values are meaningless, and exist only for future compatibility, so that future added color schemes do not invalidate the color-scheme declaration in legacy user agents.

Other Uses

You can use the color-scheme property to force a theme inside a specific component (for built-in UI and light-dark() resolution in that subtree):

.dark-only-component {
  color-scheme: dark;
}

You can tell the browser you only support one theme to prevent it from auto-adjusting built-in UI on your site.

:root {
  color-scheme: light;
}

Notes

Make sure to also include the color-scheme meta tag in the <head> of your HTML (the order matters). It can help prevent flashes during page load:

<meta name="color-scheme" content="light dark" />
Reply by email