System colors have the ability to react to the current used color-scheme
value. The light-dark()
function exposes the same capability to authors.
System Colors in CSS
In CSS you can use many colors from one of the many color spaces. For example, you can use named colors, hex colors, color functions linked to a specific color space, the more generic color()
function.
For example, the named color cornflowerblue
can also be represented as #6495ED
, or hsl(218.54deg 79.19% 66.08%)
, or color(display-p3 0.43 0.58 0.9)
.
In addition to these various names and formats, CSS includes colors described as system colors, specified in CSS Color Module Level 4. These system colors are colors defined by the browser and are represented by a keyword.
For example, the system color Canvas
–not to be confused with the <canvas>
element–represents the "background of application content or documents". It pairs nicely with, and is also meant to be used in conjunction with, CanvasText
which represents the "text in application content or documents".
In CSS, you use them as follows:
body {
color: CanvasText;
background-color: Canvas;
}
By default, CanvasText
results in a color close to black
and Canvas
is a color that's close to white
. The actual implementation depends on the browser. For example, CanvasText
in Chrome results in #121212
whereas Safari has it specified as the slightly lighter #1e1e1e
.
A hidden power of these system colors is that they can respond to the computed value of the color-scheme
property. For example, the values for CanvasText
and Canvas
get flipped around when the used color-scheme
is dark
.
:root {
color-scheme: dark;
}
body {
color: CanvasText;
background-color: Canvas;
}
In the following demo, you can change the value of color-scheme
set on :root
and see how the page responds.
- When set to
light dark
, it indicates that the element supports both light and dark mode. The choice of which value is used depends on the value of theprefers-color-scheme
media condition. - When set to
light
, it indicates that the element supports a light color scheme. - When set to
dark
, it indicates that the element supports a dark color scheme.
Introducing light-dark()
Up until now, reacting to the used color-scheme
value was something that was reserved for the system colors. Thanks to light-dark()
, specified in CSS Color Module Level 5, you now also have the same capability.
light-dark()
is a function that accepts two arguments, both of which must be a <color>
. One of both is picked depending on the used color scheme.
- If the used color scheme is
light
or unknown then the computed value of the first value gets returned. - If the used color scheme is
dark
then the computed value of the second color is returned.
The result of light-dark()
is a <color>
. It can be used in CSS anywhere a <color>
is accepted. For example in the color
and background-color
properties, but also in a function like linear-gradient()
.
In the following example, the used background-color is #333
in dark mode, or #ccc
in light mode (or an unknown mode).
:root {
color-scheme: light dark;
}
body {
background-color: light-dark(#ccc, #333);
}
Note that for light-dark()
to work correctly, you need to specify a color-scheme
. Since that property inherits, you typically set it on :root
but if you want you can choose to set it on a specific element.
Practical application
In the following example, a few custom properties represent colors on the page. To cater for dark mode, the values of those custom properties get overwritten by a different value in a prefers-color-scheme
media condition.
:root {
--primary-color: #333;
--primary-background: #e4e4e4;
--highlight-color: hotpink;
}
@media (prefers-color-scheme: dark) {
:root {
--primary-color: #fafafa;
--primary-background: #121212;
--highlight-color: lime;
}
}
Thanks to light-dark()
, this code can be simplified. Because color-scheme
is set to light dark
on :root
, the values of these colors automatically change when changing your OS from light to dark mode and vice versa.
:root {
color-scheme: light dark;
--primary-color: light-dark(#333, #fafafa);
--primary-background: light-dark(#e4e4e4, #121212);
--highlight-color: light-dark(hotpink, lime);
}
As an added bonus, it's possible to force a certain subtree of the DOM to use only light or dark mode by setting color-scheme
to either dark
or light
. In the following example, this is applied to :root
.