An easier dark mode

Four day ago, I wrote about “The prefers-color-scheme media query” and how to use it to create a dark mode for your browser. Today, I’m telling you: you might not even need it. Hm, but how do we get a dark mode then, you might ask? With a single CSS property instead of a media query.

The color-scheme property

All you need to use is one single property to tell the browser which color schemes you have. And this is how you can use it:

:root {
  color-scheme: light dark;
}

That’s it! You don’t need any more than that. Come back tomorrow for another blog post. 😁 Nah, there is more to it. But let’s see what this already does. I’ve created a page with some HTML and no CSS, other than the line above. This is how it looks like in my Chrome browser using a light mode:

Screenshot of some elements in light mode in Chrome: h1, p, fieldset, input, textarea, select and button.

And now we use the switch that I’ve shown you in the blog post “Simulate preferences in the browser” to switch to the dark mode. This is what you would get then:

Screenshot of some elements in dark mode in Chrome: h1, p, fieldset, input, textarea, select and button. The inputs and the buttons now have a background color.

While in the light mode, all elements had a white background, the form elements and the button now have a gray background. The placeholder text of the input however has a too low contrast now.

All of this we “got for free”. Just with a single line of CSS. But this design might not please you, so how can you change it, without using the media query? There are some special “functions” you can use.

The light-dark() function

Let’s take our source code from “The prefers-color-scheme media query” blog post to see how the color-scheme can be used to create a simple dark mode. This was our old code:

button {
	padding: 10px 20px;
	font-size: 2rem;
	background-color: #eee;
	border: 3px solid #333;
	border-radius: 10px;
	color: #333;
}
@media (prefers-color-scheme: dark) {
	button {
		background: #333;
		border-color: #333;
		color: #eee;
	}
}

Now, we take this code, and place every color into the new light-dark() function, that already has a good baseline support. We first set the light color and then the dark color. It is used like this:

button {
	padding: 10px 20px;
	font-size: 2rem;
	background-color: light-dark(#eee, #333);
	border: 3px solid light-dark(#333, #eee);
	border-radius: 10px;
	color: light-dark(#333, #eee);
}

Isn’t that a lot easier to read? When we view the page with a light color scheme preference, this is what we would see:

Chrome with open dev tools focused on a button. In the "Styles", the "light-dark()" function visualizes the two colors.

When you inspect the button, you can see the light-dark() function in the “Styles” and see/change the colors there. Now let’s view the same page with the dark color scheme preference:

Chrome with open dev tools focused on a button. In the "Styles", the "light-dark()" function visualizes the two colors. It simulates the dark mode.

That’s the basic usage of the color-scheme property and the light-dark() function. But the property can have different values.

Switching to a dark mode by default

If you want to use the dark mode as a default for your website and not use a light mode at all, just set the color-scheme like this:

:root {
	color-scheme: dark;
}

If you want to have a light mode by default, do the opposite, and use light as the only value. As soon as you have both values light and dark, the order is not important, you will have the behavior shown above.

Preventing the dark mode

As shown in the “Simulate preferences in the browser” blog post, Chrome has an option for an “Automatic dark mode”. This will use a dark mode, even if the color-scheme is set to light. But you can prevent a dark mode, by adding the only keyword as well:

:root {
	color-scheme: only light;
}

Now the browser will not use a dark mode. And sure enough, you can also use “only dark” to get the opposite.

Setting the property for some elements only

Some website designs have that use “different color schemes” for different element. Like a website that has a dark header, but a light footer. You might want to keep those colors, even if the modes can be switched. Then you can restrict the color-scheme for some elements, but allow both for other parts:

:root {
	color-scheme: light dark;
}
header {
	color-scheme: only dark;
}
.left {
	color-scheme: light;
}
.middle {
	color-scheme: light dark;
}
.right {
	color-scheme: dark;
}
footer {
	color-scheme: only light;
}

In this code snippet, we set both color schemes for the root element, but then change it for specific parts of the page. The header and footer are limited to just one color scheme. In the main section, we have three parts. The left and right only take one scheme, the one in the middle also takes two (we could leave property for the middle one out, as it would inherit the scheme from the root element, but for completeness, I left it here).

I’ve placed our button into each of these sections. Let’s see how this looks in Chrome with the different color scheme simulations:

With “prefers-color-scheme: light”

Chrome with "prefers-color-scheme: light" showing a dark button in the header and on the right, and light buttons on the left, in the middle and in the footer.

We can see here that our “color-scheme: dark” on the “.right” container has turned the button inside to the dark color-scheme.

With “prefers-color-scheme: dark”

Chrome with "prefers-color-scheme: dark" showing a dark button in the header, in the middle and on the right, and light buttons on the left and in the footer.

Switching to dark color scheme, the button in the middle has changed, but the other ones stayed the same. We also have a black background of the main element now, but the background colors of the header and footer stayed the same.

With “Automatic dark mode”

Chrome with "Automatic dark mode" showing a dark button in the header, in the middle and on the right, and a light button in the footer. The button on the left has a dark mode with a different border-color (darker).

Our header and footer still stay the same. But now also the left button has turned into a dark mode, since this part is not using the “only” keyword. The border color however is darker than in our defined CSS design.

Styling your dark mode even further

Since the light-dark() function can only be used for colors, you may still have to use the prefers-color-scheme media query to change other styles in your dark mode.

If you want to be even more creative, and learn deeply about dark mode option, I can recommend the “Dark Mode in CSS Guide” CSS-Trick blog posts, as well as the two pages on the color-scheme property and on the light-dark() function.

Conclusion

Adding a dark mode to your page and testing it has never been easier than with the methods described in the past blog posts. So maybe in those dark winter days, you can also adapt with the design of your website and try to create some nice dark color scheme.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

Leave a Reply

Your email address will not be published. Required fields are marked *