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" />

Browser support

Baseline 2024 New
light-dark() Usage: 90% MDN
Chrome since 123 Mar 2024
Edge since 123 Mar 2024
Firefox since 120 Nov 2023
Safari since 17.5 May 2024
iOS Safari since 17.5 May 2024
Android since 123
Reply by email