Color Intermediate

Dark mode colors without duplicating values

You defined every variable in :root and again inside @media (prefers-color-scheme: dark). light-dark() holds both values in one place so you do not repeat yourself.

Old 12+ lines
1:root {
2  --text: #111;
3  --bg: #fff;
4}
5
6@media (prefers-color-scheme: dark) {
7:root {
8  --text: #eee;
9  --bg: #222;
10}
11}
12/* Every variable declared twice */
Modern
4 lines
1:root {
2  color-scheme: light dark;
3  color: light-dark(#111, #eee);
4}

5/* One place per property */

No duplication

First argument is light, second is dark. One declaration, no @media block for each variable.

Works with variables

light-dark(var(--text-light), var(--text-dark)) fits right into a design token setup.

Any property

Use it for color, background, border-color, fill, stroke. Anything that takes a color.

Browser Support
90%
Chrome Firefox Safari Edge
Lines Saved
12+ → 4
No duplicate @media variables
Old Approach
:root + dark @media
Re-declare every variable for dark
Modern Approach
light-dark()
One value per scheme

How it works

The old approach was to set your colors (or CSS variables) in :root, then open a @media (prefers-color-scheme: dark) block and redeclare every variable or property for dark mode. That meant every color in two places and easy drift between light and dark.

The modern approach is light-dark(lightValue, darkValue). The browser picks the first value in light mode and the second in dark mode, based on prefers-color-scheme. Pair it with color-scheme: light dark so form controls and scrollbars follow. You can use raw colors or variables: light-dark(var(--text), var(--text-dark)).

ESC