CSS variables and prefers-color-scheme

November 02, 2019

According to caniuse.com, there’s a pretty good adoption of CSS variables across the board, for a total of 91.8% of global users. I was aware of CSS variables for the last few years, but I was slightly hesitant to use them.

Now, with the rollout of Dark Mode support on multiple operating systems (macOS in previous years, iOS and Android this year), it seemed prudent to look into supporting the prefers-color-scheme media query on my website. CSS variables can help in that regard.1

I use sass for my styling needs, and given that my CSS if well-written, it’s trivial to support multiple color schemes or styles. Let’s take a look at how it was before CSS variables. This a super simple example (in CSS, not SASS):

.post h1 {
    color: #444;
}
.post .content * {
    color: #333;
}

@media (prefers-color-scheme: dark) {
    .post h1 {
        color: #EEE;
    }
    .post .content {
        color: #FFF;
    }
}

The moment you have a color that appears in multiple places, you’d have to override the color there in the media query.

With variables, you can toggle the variable based on a media query. You do need to establish your variables in :root (:root is the same as styling <html> except its specificity is higher).

Here’s how I would rework the above plain CSS with CSS variables:

:root {
    --header-color: #444;
    --text-color: #333;
}

@media (prefers-color-scheme: dark) {
    :root {
        --header-color: #EEE;
        --text-color: #FFF;
    }
}

.post h1 {
    color: var(--header-color);
}
.post .content * {
    color: var(--text-color);
}

If you’re using sass, like I am on this website, you can do things like this:

$primary: #444fa0;
$primary-dark: #8DB2E5;

$background: #FFF;
$background-dark: #2C2B2C;

:root {
    --background-color: #{$background};
    --primary-color: #{$primary};
    --primary-color-ds-10: #{desaturate($primary, 10%)};
}

@media (prefers-color-scheme: dark) {
    :root {
        --background-color: #{$background-dark};
        --primary-color: #{$primary-dark};
        --primary-color-ds-10: #{desaturate($primary-dark, 10%)};
    }
}

All of this is pretty damn cool, and it means implementing support for dark mode with CSS variables for your website can be super easy. That is, if you're not running something like Tailwind or such, which also makes supporting dark mode trivial.2


  1. In Belgium, the percentage for browsers that support CSS variables seems to be lower at 73%, which means people are using terribly outdated browsers. However, looking at the overall most used browsers in Belgium, it seems the most used browsers are (as of Nov 1, 2019): Chrome (57%), Safari (21%), Firefox (6%), Edge (4%). Even Samsung's mobile browser apparently shows up if you look even lower percentages! 

  2. I like Tailwind, but I'm not convinced it is the best solution for all websites. For larger websites, applications and/or big projects, I do think it's way more practical.