CSS Media Queries Level 5 is coming and though it’s still heavily in progress, there is a particular new option that feels like a mistake in the making to me: prefers-contrast: forced. I’ll explain why I feel that way in this article.
Your dark mode toggle is broken
With more and more sites gaining support for dark mode and adding very pretty toggles to their design, it’s important to implement them correctly. Unfortunately most sites do not and as a result their toggle is broken.
Most websites that have a dark and light mode have very pretty toggles switching between some sort of sun icon, and some sort of moon icon. It’s definitely the type of element to spend (too much) time on to make it a pretty animation but it’s also important to think about what functionality you’re designing.
Do we need a toggle?
Before explaining why your dark mode toggle is broken let’s ask: do we really need a toggle to support dark mode?
The answer is not really. We can support dark mode by using the
prefers-color-scheme option built into browsers, that gives you one of three values:
With this we can implement our dark and light mode (and, for
no-preference, choose one or the other as our default). But the user might prefer your dark mode but their operating systems light mode and in that case, they’re out of luck. They can’t choose dark mode for just your site. They might not even realize your site has a dark mode.
So you’ll probably want to tell visitors your have a dark mode and let them choose which one they prefer. And a good way to do that is of course with a fancily animated toggle. (No judgement, I love a good animated toggle).
The issue is that most toggles are two states: you either have light mode or dark mode and the choice is forever stored in a cookie or localStorage. And that makes your dark mode toggle broken.
prefers-color-scheme toggles between three states, your dark mode toggle should also toggle between three states:
Dark and light seem pretty self-explanatory, but what do we mean with system? System is whatever the
prefers-color-scheme css media query gives you: light, dark or no-preference.
When the system gives you
no-preference I guess you can do what you want. But what should happen if the system tells you the user prefers light but your localStorage cookie says dark?
Most implementations I’ve seen, you’re out of luck. Once that cookie is set, you’re getting that version, and there’s no way to say “please unset the cookie and let the operating system decide”. It’s good to realize users make an explicit choice when changing their OS theme:
- Maybe I prefer my OS to be light but to switch to dark mode at sunset.
- Maybe I prefer dark mode in general, but sometimes the sun shines on my screen and then I switch to light mode to make sure I can still read what’s on my screen.
In both cases I can configure my OS to do this automatically for me, but your website will still be way too bright or unreadable dark.
How to decide?
Now the crux is: how do you decide which is more important: the explicit choice a user makes for their OS theme, or the one they made on your site?
Of course there’s no right answer there. Some people will prefer your site to always be in one theme while others want you to respond to their OS theme change. And the only way to support that is by making “let my operating system decide” an explicit option for your site.
By adding this third “system” option to your toggle, you can support not only the people that explicitly choose a color scheme for your site, but also the ones that initially want to have a look at your different versions, but otherwise prefer you to defer to the operating system.
A good example to follow is Stack Overflow’s implementation, which has these three options of light, dark and system. They wrote about here: Building dark mode on Stack Overflow.
Unfortunately they don’t go into why they chose a three-state implementation but they’re a good example to follow: make sure your dark mode toggle can switch to the system value.
Developing a website with dark mode?
Then you’ll want to use Polypane. With per-pane emulation you can easily develop your site in both dark and light mode at the same time! Try Polypane for free.