Quick Links

Chrome 76 added support for the prefers-color-scheme CSS media query, which allows websites to ask your operating system what color scheme you prefer so they can theme themselves appropriately. Here's how to set it up for your website.

What Browsers Support Dark Themes?

As of writing, most of the major browsers support dark mode, although some browsers haven't been updated to support it yet. You can check the current status on caniuse.com, which generates a support table for different browsers:

As usual, IE 11 isn't receiving any updates, and the 2% of the Internet still stuck on it won't be able to make use of it. But, those people are likely not on Windows 10, so they wouldn't see any use anyway without a dark theme to toggle.

Luckily, using prefers-color-scheme won't break your CSS, as it's an optional parameter.

How to Use CSS Color Scheme Support

To actually use prefers-color-scheme in your CSS, you'd use it as an optional media query, the same way you'd do for responsive design. For instance, if your default is white background with black text, you can use the media query to change to black background and white text.

body {

background-color: #fff;

color:#000;

}

@media (prefers-color-scheme: dark) {

background-color: #000;

color:#fff;

}

You can combine this with any other technique that you're using---for instance, you could only allow dark mode on mobile devices if you combined with a responsive media query for screen size.

Set Up a Dark Theme with CSS Variables

CSS Variables are a fairly new addition with widespread support. They're perhaps the easiest way to make a dark theme alongside prefers-color-scheme. Instead of defining color values manually, like so:

body {

background-color: #fff;

}

p {

color: #000;

}

Instead create a :root block that will apply everywhere. You can define variables here by using the double hyphen (--) followed by the variable name. Then, whenever you need to define a value, use the variable name inside the var() function instead:

:root {

--primary: #000;

--background: #fff;

}

body {

background-color: var(--background);

}

p {

color: var(--primary);

}

This method has the wonderful benefit of being able to change those variables and having changes reflect everywhere. Just below the :root block, lets add another one inside the prefers-color-scheme media query:

:root {

--primary: #000;

--background: #fff;

}

@media (prefers-color-scheme: dark) {

:root {

--primary: #ddd;

--background: #222

}

}

body {

background-color: var(--background);

}

p {

color: var(--primary);

}

This resets the variables to the dark values if the browser detects that the user prefers a dark scheme. You can manage these two palettes of colors and easily tweak them just by changing the variables.

Additionally, if you need extra CSS for the dark theme, you can place that in another prefers-color-scheme query, though you'd likely want to place that one below the rest of the CSS so it takes precedence, or use the !important flag.

Fallback For IE 11

IE 11 doesn't support this (obviously). If you want to provide IE 11 support, you can use the age old method of doubling up your properties:

p {

color: #000;

color: var(--primary);

}

This way, IE 11 will only process the first one, and see the other as invalid CSS. Dark themes won't work, but they wouldn't anyway as there's no support for the media query.

Additionally, if you don't want to use CSS variables at all, you can just completely restyle your site within the prefers-color-scheme query, but that's clunky and wastes space. If you must support every browser in existence, use the double property fallback instead.