CSS Variables Are A Sometimes Food

I’m seeing developers switch from a pre-processor like Sass to PostCSS, because the modern specs now provide everything we need, such as CSS variables (or custom properties if you’re that way inclined). However, I feel that changing to CSS variables because it’s “real CSS”, and somehow thinking you’re future-proofing your codebase is shortsighted and potentially detrimental to your users.

Variables in Sass, while also allowing more complex structures with maps and lists, actually provide a completely different use-case: they allow developers to maintain consistency throughout all the CSS, while the end users and browsers are none the wiser.

Conversely, CSS variables are dynamic. They can be changed at any time from within the browser context, and provide different opportunities such as theming on the fly.

Although using PostCSS for CSS variables is “spec-compliant”, since they aren’t backwards compatible, you’ll currently need to convert them to “static” variables; essentially simpler versions of Sass variables.

However, it is one of Sass’s main goals to not care about the syntax of CSS, thus it will not add any features that causes compatibility issues with the CSS spec.

So, unlike using PostCSS currently, we can actually benefit from using standard Sass variables and dynamic CSS ones.

Within a Sass file, we can write:

.component {
color: var(--component-color);
margin: $component-margin;

which would allow us to use consistent app-wide variables (that the browser doesn’t need to know about), as well as taking advantage of theme-level, client-side variables in modern browsers. The best of both worlds!

But… but… future-proof!

Well, if you decided to remove PostCSS when CSS variables became available in all browsers, you’d actually do your users harm.

Since Sass variables are pre-compiled and represented as standard string values in the outputted CSS, they are more performant, and a lot smaller.

To validate this, I did a quick experiment with 1000 random colors in Chrome v56 on macOS Sierra.

  1. I assigned these to class names as background colors, and applied them to 1000 <div>s; and
  2. I assigned these to CSS variables, then used these variables from within the class names, and applied them to 1000 <div>s.

Here’s an excerpt:

/* static */
.a0 { background: #55e3a4; }

.a999 { background: #9d83d4; }

which produced this:

Output of 1000 randomly colored <div>s

The difference was quite astounding.

Static Variables:

  • CSS size: 33 kB, 7.22 kB gzipped
  • Average rendering time: 15ms
Render summary of static variables

CSS Variables:

  • CSS size: 57 kB, 12.7 kB gzipped
  • Average rendering time: 51ms
Render summary of CSS variables

Since the CSS variables aren’t pre-compiled, they have to uniquely exist to be able to be used, which bloats the stylesheet, and as they’re dynamic, the browser takes longer to render them, as it has extra work to do under-the-hood.

Although 1000 variables may sound excessive, it still highlights that if you’re using PostCSS and CSS variables with the end goal of eventually removing PostCSS, your stylesheet will grow by the number of variables used; probably not what you would have intended. And, although I haven’t tested it, using CSS variables in more “expensive” properties could potentially create even larger rendering times.


  • Sass variables and CSS variables can and should have completely different use-cases.
  • Use both varieties where they make sense.
  • Don’t just switch to CSS variables to be “modern”.
  • CSS variables are a sometimes food. Enjoy in moderation.

This article has been cross-posted on Codepen.

Lead UX Engineer at @nrl. An author, speaker, artist & open sourcerer http://github.com/stowball . Devoted to #a11y, CSS, #vuejs, alt-rock, Nintendo & Charlie P

Lead UX Engineer at @nrl. An author, speaker, artist & open sourcerer http://github.com/stowball . Devoted to #a11y, CSS, #vuejs, alt-rock, Nintendo & Charlie P