Thecolor-scheme
CSS property and the corresponding meta tag
allow developers to opt their pages in to the theme-specific defaults of the user agent stylesheet.
Background
Theprefers-color-scheme
user preference media feature
The
prefers-color-scheme
user preference media feature gives developers full control over their pages' appearances.
If you are unfamiliar with it, please read my article
prefers-color-scheme
:Hello darkness, my old friend,
where I documented everything I know about creating amazing dark mode experiences.
One puzzle piece that was only mentioned briefly in the article is
thecolor-scheme
CSS property and the corresponding meta tag of the same name.
They both make your life as a developer easier
by allowing you to opt your page in to theme-specific defaults of the user agent stylesheet,
such as, for example, form controls, scroll bars, as well as CSS system colors.
At the same time, this feature prevents browsers from applying any transformations on their own.
Browser support
prefers-color-scheme
color-scheme
The user agent stylesheet
Before I continue, let me briefly describe what a user agent stylesheet is. Most of the time, you can think of the worduser agent(UA) as a fancy way to saybrowser. The UA stylesheet determines the default look and feel of a page. As the name suggests, a UA stylesheet is something that depends on the UA in question. You can have a look at Chrome's (and Chromium's) UA stylesheet and compare it to Firefox'sor Safari's(and WebKit's). Typically, UA stylesheets agree on the majority of things. For example, they all make links blue, general text black, and background color white, but there are also important (and sometimes annoying) differences, for instance, how they style form controls.
Have a closer look at
WebKit's UA stylesheet
and what it does regarding dark mode.
(Do a full text search for "dark" in the stylesheet.)
The default provided by the stylesheet changes based on whether dark mode is on or off.
To illustrate this, here is one such CSS rule using the
:matches
pseudo class and WebKit-internal variables like-apple-system-control-background
,
as well as the WebKit-internal preprocessor directive#if defined
:
input,
input:matches([type= "password" ], [type= "search" ]) {
-webkit-appearance: textfield;
#if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
HAVE_OS_DARK_MODE_SUPPORT
color: text;
background-color: -apple-system-control-background;
#else
background-color: white;
#endif
/* snip */
}
You will notice some non-standard values for thecolor
andbackground-color
properties above.
Neithertext
nor-apple-system-control-background
are valid CSS colors.
They are WebKit-internalsemanticcolors.
Turns out, CSS has standardized semantic system colors.
They are specified in
CSS Color Module Level 4.
For example,
Canvas
(not to be confused with the<canvas>
tag)
is for the background of application content or documents,
whereas
CanvasText
is for text in application content or documents.
The two go together and should not be used in isolation.
UA stylesheets can use either their own proprietary or the standardized semantic system colors,
to determine how HTML elements should be rendered by default.
If the operating system is set to dark mode or uses a dark theme,
CanvasText
(ortext
) would be conditionally set to white,
andCanvas
(or-apple-system-control-background
) would be set to black.
The UA stylesheet then assigns the following CSS only once, and covers both light and dark mode.
/**
Not actual UA stylesheet code.
For illustrative purposes only.
*/
body {
color: CanvasText;
background-color: Canvas
}
Thecolor-scheme
CSS property
TheCSS Color Adjustment Module Level 1 specification introduces a model and controls over automatic color adjustment by the user agent with the objective of handling user preferences such as dark mode, contrast adjustment, or specific desired color schemes.
Thecolor-scheme
property defined therein allows an element to indicate
which color schemes it is comfortable being rendered with.
These values are negotiated with the user's preferences, resulting in a chosen color scheme
that affects user interface (UI) things such as the default colors of form controls
and scroll bars, as well as the used values of the CSS system colors.
The following values are currently supported:
normal
Indicates that the element is not aware of color schemes at all, and so the element should be rendered with the browser's default color scheme.[ light | dark ]+
Indicates that the element is aware of and can handle the listed color schemes, and expresses an ordered preference between them.
In this list,light
represents a light color scheme,
with light background colors and dark foreground colors,
whereasdark
represents the opposite, with dark background colors and light foreground colors.
For all elements, rendering with a color scheme should cause the colors used in all browser-provided UI for the element to match with the intent of the color scheme. Examples are scroll bars, spellcheck underlines, form controls, etc.
On the:root
element, rendering with a color scheme
additionally must affect the surface color of the canvas (that is, the global background color),
the initial value of thecolor
property, and the used values of the system colors,
and should also affect the viewport's scroll bars.
/*
The page supports both dark and light color schemes,
and the page author prefers dark.
*/
:root {
color-scheme: dark light;
}
Thecolor-scheme
meta tag
Honoring thecolor-scheme
CSS property requires the CSS to be first downloaded
(if it is referenced via<link rel= "stylesheet" >
) and to be parsed.
To aid user agents in rendering the page background with the desired color schemeimmediately,
acolor-scheme
value can also be provided in a
<meta name= "color-scheme" >
element.
<!--
The page supports both dark and light color schemes,
and the page author prefers dark.
-->
<meta name= "color-scheme" content= "dark light" >
Combiningcolor-scheme
andprefers-color-scheme
Since both the meta tag and the CSS property (if applied to the:root
element)
eventually result in the same behavior, I always recommend specifying the color scheme
via the meta tag, so the browser can adopt to the preferred scheme faster.
While for absolute baseline pages no additional CSS rules are necessary,
in the general case you should always combinecolor-scheme
withprefers-color-scheme
.
For example, the proprietary WebKit CSS color-webkit-link
,used by WebKit and Chrome
for the classic link bluergb(0,0,238)
,
has an insufficient contrast ratio of 2.23:1 on a black background and
fails
both the WCAG AA as well as the WCAG AAA
requirements.
I have opened bugs forChrome, WebKit,and Firefox as well as ameta issue in the HTML Standard to get this fixed.
Interplay withprefers-color-scheme
The interplay of thecolor-scheme
CSS property and the corresponding meta tag
with theprefers-color-scheme
user preference media feature may seem confusing at first.
In fact, they play together really well.
The most important thing to understand is thatcolor-scheme
exclusively determines the default appearance,
whereasprefers-color-scheme
determines the stylable appearance.
To make this clearer, assume the following page:
<head>
<meta name= "color-scheme" content= "dark light" >
<style>
fieldset {
background-color: gainsboro;
}
@media (prefers-color-scheme: dark) {
fieldset {
background-color: darkslategray;
}
}
</style>
</head>
<body>
<p>
Lorem ipsum dolor sit amet, legere ancillae ne vis.
</p>
<form>
<fieldset>
<legend>Lorem ipsum</legend>
<button type= "button" >Lorem ipsum</button>
</fieldset>
</form>
</body>
The inline CSS code on the page
sets the<fieldset>
element'sbackground-color
togainsboro
in the general case,
and todarkslategray
if the user prefers adark
color scheme
according to theprefers-color-scheme
user preference media feature.
Via the<meta name= "color-scheme" content= "dark light" >
element,
the page tells the browser that it supports a dark and a light theme,
with a preference for a dark theme.
Depending on whether the operating system is set to dark or light mode, the whole page appears light on dark, or vice versa, based on the user agent stylesheet. There isnoadditional developer-provided CSS involved to change the paragraph text or the background color of the page.
Note how the<fieldset>
element'sbackground-color
changes
based on whether dark mode is enabled, following the rules
in the developer-provided inline stylesheet on the page.
It is eithergainsboro
ordarkslategray
.
![A page in light mode.](https://web.dev/static/articles/color-scheme/image/a-page-light-mode-20033c5b52e57.png)
<fieldset>
element'sbackground-color
isgainsboro
as per the inlined developer stylesheet.
![A page in dark mode.](https://web.dev/static/articles/color-scheme/image/a-page-dark-mode-db72ce14278ec.png)
<fieldset>
element'sbackground-color
isdarkslategray
as per the inlined developer stylesheet.
The<button>
element's appearance is controlled by the user agent stylesheet.
Itscolor
is set to the
ButtonText
system color, and itsbackground-color
and the fourborder-color
s are set to the system color
ButtonFace
.
![A light mode page that uses the ButtonFace property.](https://web.dev/static/articles/color-scheme/image/a-light-mode-page-uses-2d1dbd77e94d4.png)
background-color
and the various
border-color
s are set to theButtonFace
system color.
Now note how the<button>
element'sborder-color
changes.
Thecomputedvalue for theborder-top-color
and theborder-bottom-color
switches fromrgba(0, 0, 0, 0.847)
(blackish) torgba(255, 255, 255, 0.847)
(whitish),
since the user agent updatesButtonFace
dynamically based on the color scheme.
The same applies for the<button>
element'scolor
that is set to the corresponding system colorButtonText
.
![Showing that the computed color values match ButtonFace.](https://web.dev/static/articles/color-scheme/image/showing-the-computed-col-b5a5bb27a14d7.png)
border-top-color
and theborder-bottom-color
that are both set toButtonFace
in the user agent stylesheet are nowrgba(0, 0, 0, 0.847)
.
![Showing that the computed color values still match ButtonFace while in dark mode.](https://web.dev/static/articles/color-scheme/image/showing-the-computed-col-fbfce1c6513a9.png)
border-top-color
and theborder-bottom-color
that are both set toButtonFace
in the user agent stylesheet are nowrgba(255, 255, 255, 0.847)
.
Demo
You can see the effects ofcolor-scheme
applied to a large number of HTML elements
in ademo on Glitch.
The demodeliberatelyshows the WCAG AA and WCAG AAA
violation
with the link colors mentioned in the warning above.
![The demo while in light mode.](https://web.dev/static/articles/color-scheme/image/the-demo-while-light-mod-8d16b35fd6de9.png)
color-scheme: light
.
![The demo while in dark mode.](https://web.dev/static/articles/color-scheme/image/the-demo-while-dark-mode-9f130b7310353.png)
color-scheme: dark
.
Note the WCAG AA and WCAG AAA
violation
with the link colors.
Acknowledgements
Thecolor-scheme
CSS property and the corresponding meta tag were implemented by
Rune Lillesveen.
Rune is also a co-editor of the CSS Color Adjustment Module Level 1 specification.
Hero image by
Philippe Leone
onUnsplash.