Artboard 16light, inspiration, solution, idea, innovation,Google Sheets iconSwift icon
Published at
Updated at
Reading time
4min
This post is part of my Today I learned series in which I share all my web development learnings.

User preferences and settings play an essential role in how websites look in 2020. To name two examples: well-made websites look great on different devices and handle various font-size settings with ease.

Over the past few years, a new user preference made it into the group of things "that change how a website looks" – yes, I'm talking about color themes. "How to implement dark mode on a website?" was one of the most important topics in 2019.

(yes... this site will have a dark mode eventually, too)

But how can you enable dark mode then? With today's web technology, your site can react to your visitors' color preferences (coming from the operating system) using the prefers-color-scheme media query. This media query allows you to write CSS depending on the preferred color scheme.

--color-one: #ff0000;
--color-two: #00ff00;

@media (prefers-color-scheme: dark) {
  /* redefine dark mode colors here */
  --color-one: #00ffff;
  --color-two: #ff00ff;
}

Technically, this approach is straightforward, but implementing high-quality theme handling is not trivial. It includes way more than just switching some colors. To learn more, I recommend reading Thomas Steiner's excellent guide on this topic: "prefers-color-scheme: Hello darkness, my old friend".

Don't forget to indicate your site's supported color schemes

Having the ability to style websites depending on user color settings is excellent, but unfortunately, it's not covering the whole picture. So what's missing?

Even after writing hundreds of custom CSS lines, you'll find that some elements will still rely on browser default styling. It could be a text input field, a checkbox, a radio button, or even the good old scroll bar using the browser's user agent stylesheet. The problem is that the browser doesn't know about your defined CSS color schemes.

To make all your UI elements dark mode compatible, you would have to define and overwrite all these CSS rules from the user agent stylesheet. This process is not ideal!

The color-scheme property helps here. It allows you to give browsers the information on your website's supported color schemes.

color-scheme accepts two values:

  • normal – your site/an element does not support color schemes
  • [ light | dark | <custom-ident> ]+ – your site or a specific element can be rendered with the defined color schemes (custom-ident is currently unsupported and is only defined for possible future use cases)

You can set these values as an HTML meta element or as a CSS declaration.

<!-- Hey Browser, 
     this website support `dark` and `light`
     but the author prefers `dark` representation -->
<meta name="color-scheme" content="dark light">
:root {
  /* Hey Browser, 
     this website support `dark` and `light`
     but the author prefers `dark` representation */
  color-scheme: dark light;
}

With this information, browsers can improve their default styling to match the defined color schemes. You don't have to overwrite every color to make an element dark mode compatible because the browser took care of it already.

The spec defines the following behavior when a color-scheme property is defined:

If the author has indicated that the page can support this color scheme, the user agent must match the following to the user’s preferred color scheme:

  • the color of the canvas surface
  • the default colors of scrollbars and other interaction UI
  • the default colors of form controls and other "specially-rendered" elements
  • the default colors of other browser-provided UI, such as "spellcheck" underlines

Speaking of dark mode, this paragraph states that: if a site claims to support a dark color scheme and the user prefers a dark color scheme, the browser must provide dark mode compatible colors, form controls, scroll bars and other UI elements.

This browser feature makes it easier to build color-schemed UIs because default UI elements adjust their color automatically. You can avoid overwriting every color! πŸŽ‰

Browser support of color-scheme

If you go to caniuse.com to check the browser support of color-scheme, you'll be surprised. It looks reasonably good and it seems that only Firefox is missing to support color-scheme.

caniuse.com support table showing that color-scheme is mainly supported only with Firefox missing

Update: Firefox will support color-scheme starting with v96.

Unfortunately, the support table is not telling the whole truth. According to the specification "real support" for color-scheme consists of two things:

  1. the browser must technically support the color-scheme property
  2. the browser must adjust colors and provide UI elements taking color-scheme into consideration

Chromium browsers supported color-scheme but didn't render UI elements accordingly when this post was written. Make sure to check Thomas Steiner's color-scheme test page with the browsers you support. The page toggles the color-scheme property every few seconds going from light to dark and back. This approach allows us to have a look at which elements react to different color schemes.

With Firefox v96 starting to support color-scheme, we're now close to a cross-browser support. See below that the major browsers render UI controls correctly. πŸŽ‰

Chrome, Edge, Firefox and Safari rendering dark UI controls.

Should you use the color-scheme property today?

This web platform addition is precious, and while we don't have complete cross-browser support today, color-scheme support in Chromium and Safari covers the big majority. If you consider that Firefox will ship it soon, too, I think it's good to go!

For my site, I'll add <meta name="color-scheme" content="normal"> to this site until I finally support dark mode. πŸ™ˆ

Additional resources

Related Topics

Related Articles