Thinking dark thoughts

As Dark Mode grows in use, it’s easy to make your site dark-friendly.


General note: This site’s appearance, configuration, hosting, and other basic considerations will change over time. As a result, certain content on this page could be at variance with what you’re currently seeing on the site, but the two were consistent when this post originally appeared.

With the recent release of iOS 13, system-wide Dark Mode finally became available to iPhone and iPad users. That means a massive number of people are now going to be looking at apps and websites in completely different ways than before.1 Moreover, browsers on both mobile devices and the desktop are getting increasingly Dark Mode-savvy, switching between Light and Dark Modes fairly seamlessly.

However, if you don’t make the proper adjustments to your website and it’s in the more traditional dark-content-on-a-bright-background motif, Dark Mode users might get a rude jolt when they stop by. It’s sort of like what happens when you’ve been sitting in a dark room watching TV and suddenly somebody comes in and turns on all the lights. Might not be all that welcome.

Fortunately, it’s easy to fix. Well, relatively easy.


CSS has a media query feature called prefers-color-scheme (explained well and in detail, as are so many things, on MDN). All you have to do is wrap, within such a media query, the CSS which will control how your site looks when a Dark Mode user visits.

Here’s a bare-bones example.

Let’s say your <body> element currently is set to have a white background and very dark gray text, like so:

body {
	background: #fff; /* totally white */
	color: #333; /* very dark gray, almost black */

To resolve this for Dark Mode, you could do it this way.

body {
	background: #fff; /* totally white */
	color: #333; /* very dark gray, almost black */

@media (prefers-color-scheme: dark) {
	this is what happens if the user
	selects Dark Mode
	body {
		background: #000; /* totally black */
		color: #fff; /* totally white */

With this CSS in place, a Dark Mode visitor sees everything with white text on a jet-black background. People whose devices have OLED screens will especially appreciate that totally black background because it will save battery juice, since a truly black pixel on an OLED screen uses no power.

On the other hand, if your site already had a dark appearance but you want to give a different look to folks who don’t have Dark Mode in use, the prefers-color-scheme feature also lets you choose light, so you could do similar work to make the site appear brighter for those users.

A few nits (pardon the pun)

[See, nits are units used to express screen brightness, so — ahh, never mind.]

Of course, it’s not that easy. Cool stuff never is.

The thing is, you probably should adjust all of your site’s bright elements within prefers-color-scheme. To repeat the analogy of the dark room, anything you miss will be a flashlight from the distance that suddenly jabs the person in their widened pupils. Not nice. So, if your CSS already has a lot of stuff, you may have to include quite a few things in that media query.

Two things can make it particularly complicated.

Using code blocks

If yours, like mine, is a site where you sometimes use code blocks (like the ones above) to show others how HTML, CSS, JavaScript, or some other code should look, that gets a little hairy, especially if you’re using something like Chroma or PrismJS to provide color-coding for easier reading.

If you look at the source for such code blocks, you’ll notice they have a lot of different <span>s in them to provide the various color treatments. So — assuming you weren’t already using a dark background scheme for your code blocks, as some do — you’re going to have to reassign the colors for not only the code block backgrounds but also each of the individual color codes.

Yes, that can be tedious, particularly if you haven’t yet done code blocks with that many different languages, because each language has its own specific color-coding and, as you do a code block in a language you haven’t previously included, you’ll see new combinations; so, as in all things web dev, you’ll first need to test (and fix) locally.

External iframes

And then there are those third-party iframes you can’t control, at least not all that well.

Note, 2020-08-08: The following explanation was from before I stopped embedding third-party content, such as from Twitter, as a result of this site’s belatedly adopted privacy policy.

In my site’s case, Twitter is the chief offender. Dark Mode and the default white Twitter background do not play nicely together. So I followed Twitter’s dev docs and, through JavaScript-adjusted <meta> tags, told my site’s embedded Twitter content to “listen” to the user’s Dark Mode/Light Mode setting and change accordingly.2

That sounded good in theory, but so far hasn’t worked all that well in practice. I’ve found that only Firefox seems to respect the change without requiring a reload of the page, and even Firefox sometimes lets me down. I suspect I’m missing something, but it may simply be that Twitter doesn’t necessarily respect that <meta> tag method as much as its dev docs say it does. We Shall See.

But it’s still a good idea

All that said, I still encourage you to make your site friendly to both Light Mode and Dark Mode. Once you do, the changes will make visiting your site considerably more pleasant to your users, and that should translate into repeat visits. At the very least, it should help make sure that Dark Mode users don’t yell, “Augghhh!!! My eyes!” and never return — at least, as long as your site doesn’t resemble something from the GeoCities days. If it does, well, you’re on your own.

  1. Android users have had Dark Mode since the release of Android P last year — at least, for those Android users who actually got to upgrade to Android P — and any number of apps on both iOS and Android have provided at least some form of Dark Mode. But, due to the sheer quantity of iOS users (especially in North America) and the likelihood that the vast majority of them will be on iOS 13 fairly quickly if iOS 12 adoption was any reliable measuring stick, it’s especially significant that iOS 13 adds Dark Mode as a system-wide option. ↩︎

  2. For those odd cases where JavaScript is disabled, I use <noscript> code to make Dark Mode the default setting for the Twitter content. I figure it’s safer to show Dark Mode stuff to Light Mode users as opposed to the other way around. ↩︎