Starbeamrainbowlabs

Stardust
Blog

Using prefers-color-scheme to display alternate website themes

Support for the prefers-color-scheme landed in Firefox 67 beta recently. While it's a little bit awkward to use at the moment, it enables support for a crucial new feature on the web: Changing the colour scheme of a webpage based on the user's preference.

If a user is outside on a sunny day, they might prefer a light theme whilst browsing the web. However, if they are at home on an evening when it's dark, they might prefer a dark theme.

Traditionally, some websites have supported enabling a site-specific option in their settings, but this requires that the user enable an option manually when they visit the website - and has to be reset on every device and in every private browsing session.

The solution to this is the new prefers-color-scheme CSS level 5 media query. It lets you do something like this:

body {
    background: red; /* Fallback */
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
    body { background: #333; color: #efefef; }
}
/* Light theme */
@media (prefers-color-scheme: light),
    (prefers-color-scheme: no-preference) {
    body { background: #efefef; color: #333; }
}

Hey presto - the theme will now auto-change based on the user's preference!

Here's a live demo of that in action:

See the Pen prefers-color-scheme demo by Starbeamrainbowlabs (@sbrl) on CodePen.

(Can't see the above? Try a direct link.)

Current Support

Currently, Firefox 67+ and Safari (wow, who knew?) support the new media query - as of the time of typing. For Firefox users, the preferred colour scheme is autodetected based on your operating system's colour scheme. Here's the caniuse.com support table, which should always be up-to-date:

If this doesn't work correctly for some reason (like it didn't for me on Ubuntu with the Unity Desktop - apparently it's based on the GTK theme on Ubuntu), then you can set it manually in about:config. Create a new integer value called ui.systemUsesDarkTheme, and set it to 1.

If you accidentally create a string by mistake, you'll need to close Firefox, find your profile folder, and edit prefs.js to force-change it, as about:config isn't capable of deleting or altering configuration directive types at this time (yep, I ran into this one!).

Making use of CSS Properties

Altering your website for dark-mode readers isn't actually all that hard. If you're using CSS Properties already, you might do something like this:

:root {
    --background: #efefef;
    --text-colour: #333;
}

@media (prefers-color-scheme: dark) {
    :root {
        --background: #333;
        --text-colour: #efefef;
    }
}

body {
    background: var(--background);
    color: var(--text-colour);
}

(Want a demo? Click here!)

This way, you can keep all the 'settings' that you might want to change later at the beginning of your CSS files, which makes it easy to add support for dark mode later.

I know that I'm going to be investigating adding support to my website at some point soon (stay tuned for that!).

Found this interesting? Got a cool resource to aid in colour scheme design? Found another great CSS feature? Comment below!

Sources and Further Reading

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression containerisation css dailyprogrammer data analysis debugging demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference releases rendering resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial tutorials twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

Archive

Art by Mythdael