Easier dark-mode CSS with Sass
Published on .When offering a dark-mode for a website, you probably want to offer an "automatic" or "system" option which follows the OS-level user preference for dark mode instead of explicitly forcing a light or dark mode.
This way, visitors can choose:
dark
: for always dark-modelight
: for always light-modeauto
: for automatically switching between dark/light based on operating-system setting.
Writing the CSS for dark-mode that covers these options currently requires a lot of boilerplate, however. With the setup and the Sass mixin I'm sharing next, it should hopefully be easier to handle this.
Note: we're not focusing on the mechanics of how to switch between these options using JavaScript in this post. We're focusing on the CSS implementation specifically.
The setup #
On your document, you're going to add a data-theme
attribute to the root <html>
whose value will be the currently chosen option:
<!-- always dark-mode -->
<html data-theme="dark"></html>
<!-- automatic / based on system preference -->
<html data-theme="auto"></html>
Again, how you chose to update this value on your pages is outside of the scope of this post.
The Sass Mixin #
Here's the mixin that takes care of everything:
@mixin on-dark-mode {
@media (prefers-color-scheme: dark) {
html[data-theme="auto"] & {
@content;
}
}
html[data-theme="dark"] & {
@content;
}
}
And here's how to use it:
.some-component {
// base / light-mode styles
--bg-color: white;
background-color: var(--bg-color);
color: black;
// dark-mode styles
@include on-dark-mode {
--bg-color: black;
color: white;
}
}
I use this mixin in any Sass project I work on, and so far it has worked nicely!
Limitations: can't be used for root/html styles #
The only downside to this mixin (that I'm aware of) is that it can't be used for declaring dark-mode styles in the :root
or html
element;
it only works for decendants of it, starting with body
.
This means it can't be used to define a set of "global" colors as Custom Properties to be updated based on dark-mode, for instance.
The future: simpler implementation #
Hopefully sometime later in 2023 we will be able to use style queries to simplify and shorten the code needed for robust dark-mode support.
More about: development code-snippet css sass