Simplified Dark Mode With Style Queries

Feb 27, 2023

Style queries are an extended part of the containment spec which container queries also came from. TL;DR: they allow you to query for style features of a container and apply rules to its children.

For example, if the --theme custom property has the value dark, then you can style child elements with a dark theme. This specific ability to query custom property values is available as of Chromium 111. If you're reading prior to March 7, you'll want to visit the demos in Chrome Canary.

So, how does that help us simplify defining dark mode styles?

Here's the "old" way if you needed to support both user preference and a setting from a theme toggle:

/* User preference */
@media (prefers-color-scheme: dark) {
body {
background-color: black;
color: white;
}
}

/* Set via JS or server-side post form submit */
body[data-theme="dark"] {
background-color: black;
color: white;
}

The duplication of the style blocks is necessary because there is no way to combine a selector with a media query.

However, with style queries, we can modify our setup and only write the dark theme/mode styles once!

Unlike the need to define containment for size container queries to work, all elements are inherently style containers. This means we can use style queries against any element without an extra step!

So, for both of the conditions we previously had for the user preference and custom data attribute, we'll simply set the custom property of --theme. Following that, our style query picks up that value and applies the dark theme styles.

/* User preference */
@media (prefers-color-scheme: dark) {
html {
--theme: dark;
}
}

/* Set via JS or server-side post form submit */
html[data-theme="dark"] {
--theme: dark;
}

/* Attach dark mode styles */
@container style(--theme: dark) {
body {
background-color: black;
color: white;
}
}

You can certainly specify styles for light mode as well, or flip the logic if your site defaults to a dark theme. A reminder that this isn't production-ready today, but it may be at least a progressive enhancement candidate towards the end of 2023!

Learn more about style queries

Una shows examples to get started with style queries, and notes the outstanding issues that will help make the spec even more powerful. I also recommend her earlier personal post with even more examples of style queries. Another outstanding resource is Ahmad Shadeed's overview of use cases for style queries.