Sassy dark mode
Backward compatible dark mode
The easiest way to implement dark mode these days is with CSS3 custom properties (variables). Just have a :root
element with default colors, and then another one under a media query, and let the user preference do the work. Something like this:
:root { --bkg: white; --txt: black; } @media ( prefers-color-scheme: dark ) { :root { --bkg: black; --txt: white; } } body { background: var(--bkg); color: var(--txt); }
And if the browser doesn’t understand or have the preference, it would take the first set of variables. But if it doesn’t understand variables at all, that’s a problem.
I really hope there is a better solution, because mine feels very silly, but it works. Sass variables. Bare minumum primer: Sass is a preprocessor, it creates a regular CSS file and all the magic happens before that. Also, there’s a pain point if you’re adapting an existing stylesheet: it’s better if the color information has its own section. Lucky for me, I have been doing this since time immemorial.
Ok, to get to the point, we need 6 files. Did I mention it’s silly? style.scss
is our main file, which would be our actual style.css
at the end. _colors.scss
is our color information where we will write it with our variables. Two files for the light and dark variables themselves and two to make a magic trick work.
So, the magic trick is this: we import two files into our main file, and both of those files import a set of variables and our colors file:
_vars_light.scss
+ _colors.scss
→ _magic_light.scss
_vars_dark.scss
+ _colors.scss
→ _magic_dark.scss
_magic_light.scss
+ _magic_dark.scss
→ style.scss
So style.scss
would have this:
@import "magic_light"; @media ( prefers-color-scheme: dark ) { @import "magic_dark"; }
_magic_light.scss
would have this:
@import "vars_light"; @import "colors";
_vars_light.scss
would have this:
$bkg: white; $txt: black;
And _colors.scss
would have this:
body { background: $bkg; color: $txt; }
_magic_dark.scss
and _vars_dark.scss
would “mirror” _magic_light.scss
and _vars_light.scss
.
BTW, there may be different requirements for how Sass files are handled, I just go by what Hugo does with them and what works for me.
In the end, we have a rather large style.css
file with a default light style and a dark style under a media query. Kind of like what we did with CSS3 variables, but that works without them. Silly!
A bit more about Sass.