Sass In The Dark

Jun 28, 2019 • Intuitively Implementing Dark Mode With SCSS

As a iOS developer by day, working on web technologies, while not foreign, is something I am working on improving. I've been diving into React on the web, and more complex web development flows. I've definitely had my gripes with CSS, so I decided to take the time to learn SCSS.

In 2018 Apple released Dark Mode for macOS. I actually sat in the same office as the team that worked on it during my internship on the Foundation team. We all knew that dark mode adoption wouldn't really become widespread until iOS included the feature, which happened the following year. Dark mode will be on hundreds of millions of devices in the fall, and mobile users will get to live in the joy of getting their eyes seared medium rare at 1 am when trying to look up the meaning of gabelle. For those wondering: it's a tax on salt imposed in France before 1790.

I was pretty shocked that there isn't an intuitive way to observe dark mode plastered around the internet, since it seems like it should be a pretty common question. Anyway, enough with the modern day online recipe life story, let's get to the code.

Plain CSS

In plain CSS, observing dark mode is pretty simple.

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

As a true programmer, I like to keep things simple. Since this is the standard method for observing dark mode state, how can I use this to my advantage?

Incorporating SCSS

SCSS gives you some pretty awesome features, like @import that can be used to your advantage. In web development, keeping things modular is a must. Importing extranious code is one of the best ways to ensure a bad user experience, and have styles clash with eachother, so let's arrange our solution in a way that promotes modularity by having seperate SCSS files for dark mode and light mode. That way, we can have one index file that conditionally imports the light, or dark mode stylesheet. "But conditional importing is illegal" you might say, and you're right! And that's where we tie in a little plain CSS magic, and beat around the bush. Time to get off of your SCSS high horse.

So in conclusion, if you arrange your files correctly, as I have done below,

[SCSS DIRECTORY]
    |
    |_ lightmode.scss
    |_ darkmode.scss
    |_ index.scss
                    

then your index.scss can act as a header for the two styles.

                        
@media (prefers-color-scheme: dark) {
    @import "darkmode";
} 

@media (prefers-color-scheme: no-preference) {
    @import "lightmode";
}
@media (prefers-color-scheme: light) {
    @import "lightmode";
}
                    

So while we're not technically conditionally importing, we technically are, while adhereing to the constraints to SCSS.

Other Ideas

While having two files kind of seems like overkill, I believe that it is the best way to attack this problem. This gives you the most control over every aspect of each style appearence. It also allows for easy adaptation, and extension, so if/when new color schemes come out (maybe some accessibility options?) get supported, you can easily add a stylesheet.

Not everything has to be divorced though. By importing the index (or another "header"), you can keep a log of global colors. Just be sure to specify light, and dark mode varients.

If you have any questions, comments, ideas, or improvements to suggest, please send me an email.

I am in the process of adding dark mode support to my website.