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 play an essential role in how websites look in 2020. Two examples: well-made websites look great on different devices and handle various font-size settings with ease. But there's more!

Over the past years, a new 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? With today's web technology, your site can react to your visitors' color preferences (which come 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 coming from the operating system.

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

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

The media query approach seems straightforward, but implementing high-quality theme handling is everything but trivial because it includes way more than just switching some background and text colors.

To learn more, I recommend reading Thomas Steiner's excellent guide on this topic: "prefers-color-scheme: Hello darkness, my old friend".

So, what else should you consider when implementing dark mode?

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

Even after writing hundreds of custom CSS lines, you'll find elements that 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. And all these elements receive styles for light mode.

The problem is that the browser doesn't know about your media queries and custom CSS color schemes.

To make all your UI elements (and I really mean all of them) dark mode compatible, you must define and overwrite all these CSS rules from the user agent stylesheet. This process is not ideal and nobody got time for that!

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;
}

Browsers can then adjust their default styling to match the desired color scheme with this information. You don't have to overwrite every color to make an element dark mode compatible because the browser has taken care of it already. Sweet!

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; the above paragraph means 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 system colors, form controls, scroll bars and other UI elements.

The color-scheme browser feature makes it easier to build color-schemed UIs by automatically adjusting default UI element colors so that you don't have to overwrite every tiny bit. πŸŽ‰

The color-scheme browser support

So, can you use color-scheme today? Here's the support info from MDN. πŸ‘‡

MDN Compat Data (source)
Browser support info for color-scheme
chromechrome_androidedgefirefoxfirefox_androidsafarisafari_iossamsunginternet_androidwebview_android
8181819696131313.081

But unfortunately, the support table is not telling the whole truth. According to the specificationm, "real support" for color-scheme includes 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. 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 look at which elements react to different color schemes.

With Firefox v96 starting to support color-scheme, all major browsers support it! See the major browsers rendering UI controls correctly below.

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

Should you use the color-scheme property today?

Go for it! I don't see a reason not to!

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

Additional resources

Was this TIL post helpful?
Yes? Cool! You might want to check out Web Weekly for more quick learnings. The last edition went out 18 days ago.
Stefan standing in the park in front of a green background

About Stefan Judis

Frontend nerd with over ten years of experience, freelance dev, "Today I Learned" blogger, conference speaker, and Open Source maintainer.

Related Topics

Related Articles