CSS: prefers-color-scheme
When developing tools that interface with users in a visual sense, I believe it is important to cater to the users’ wants (and needs) as much as possible, whilst retaining a recognizable product identity. Probably the brightest decision in this regard is the background color: light or dark?
Specifically regarding webpages, a variety of solutions have been developed: JavaScript triggers, cookie-based theming, user stylesheets and time-based theming. All of these solution falls short in one important aspect: they do not cover 100% of a user’s interaction with a site. The first two solutions have no safe default - they may always show the user the “wrong” theme first, and require active engagement to fix, which is a burden on the user. User stylesheets do work on first visit, however one often has to deal with broken sites, since they were not designed for theming. Finally, time-based theming is silly in its own right1.
The solution
In 2017, the CSS Media Queries Level 5
specification was released, and it proposes the best solution to date: a media
query named prefers-color-scheme
. It is set by your browser, and can be set to
either light
or dark
- more values may be supported in the future. Instead
of requiring a user to interact with each site they visit, the decision is
only made once at the browser, and can be applied to every site, even on the
first visit! And it is supported by all major desktop and mobile
browsers, simply marvelous.
Using this feature is as simple as adding a media query to your styling. Using CSS custom properties (“variables”), all you need to do is define the appropriate colors and you’re good to go.
@media (prefers-color-scheme: light) {
// light styling
// the default if no preference set
}
@media (prefers-color-scheme: dark) {
// dark styling
}
The prefers-color-scheme
still has one drawback: correct page rendering must
be delayed until CSS is downloaded and parsed, and might cause flickering on
slow connections, when the browser defaults to a white background but the user
prefers dark mode for example. Using the color-scheme
meta tag, the webpage
can immediately signal which themes it supports, and the browser can react by
styling the background dark immediately, before applying CSS, which prevents
the aforementioned flickering. The first named theme is the author’s preferred
default, which the browser can respect if the user has not given an explicit
preference.
<!-- supports light and dark mode, defaults to light mode-->
<meta name="color-scheme" content="light dark">
Trying it out
This website fully supports theme selection based prefers-color-scheme
, try it
out! It even inverts images2 to perfectly match your preferred style, a
feature I’m very proud of, even if it is virtually invisible (since almost
nobody looks at both styles). See the website’s
source to see the actual SCSS source
files.
On desktop browsers you can test it using the developer tools (Firefox, Chrome, Safari). On mobile, modern smartphones (both iOS and Android) set your preferred color scheme based on the system theme, so changing that should also change the appearance of this site.
Sadly, many of the sites I interact with daily do not support
prefers-color-scheme
. Especially people who rarely do frontend work (such as
myself) may not know of this feature, and I hope to raise awareness for
user-friendly theme support.
If you have a personal blog, product or company website or any other side,
consider adding support for prefers-color-scheme
to your theme. Even though it
has no impact on the majority of people, we ultimately want design our products
to be as user-friendly as possible. Right?