CSS variables, like variables in any programming language, let us reference the same values over and over. As of April 2017, they are supported by all modern browsers and are an effective way to write tight, clean styles.

I’ll be walking through the basics of CSS variables, how they are different from Sass variables, and how to provide legacy support.



Any CSS property — color, size, position, etc. — can be stored in a CSS variable. Their names are all prefixed with --, and you declare them by adding them to an element right where you add its other styles:

You refer to a CSS variable by wrapping it in var().

If you look at this CSS in your web inspector, you’ll see that these variables are not being aliased or transpiled in any way — your browser will tell you that an a‘s color is --primary, not the hex value itself.

When you use a CSS variable, you can also pass in an optional default value:

This default value will be used if the CSS variable is not defined or available in the current scope.


Scoping and the cascade

CSS variables act like a normal style property; a variable is available anywhere down the cascade.

For example, these variables can be used by anything on the entire page:


And these will only be defined within elements with a certain class:


In this second example, if you try to use --primary outside of a .content element, the page will still render but that style will not be applied.

The Paradigm: custom CSS properties

You may have noticed a theme so far, which is that variables act just like other CSS properties. You declare variables where you set properties, they cascade in the same way, and so on.

This is because CSS variables are actually nothing more than custom properties. The only difference between --primary and position is that position always means something specific and directly affects rendering, whereas --primary does nothing until it is explicitly used.

CSS variables being supported by a browser means that the browser allows the user to set arbitrary, namespaced CSS properties. This is really exciting. Just like how it’s exciting that media queries let us get away from resize listeners in JavaScript, CSS variables are opening the door to a future that relies less on JS and preprocessors. Speaking of which…

Better than Sass: theming

CSS variables aren’t analogous to Sass variables, and in some ways, the former are vastly preferable to the latter. One of these situations is when you’re looking to swap out themes. On my personal site, I randomly theme the page each time it is loaded; the user can end up with any of nine color schemes.

This is easily done using Sass. Store your color combinations in Sass maps, loop over them, and you can quickly create a bunch of classes that you can apply to the page:


The CSS is easy to generate, but in the case of nine variations, you end up with eight classes’ worth of styling that remains unused.

CSS variables can achieve the same effect with no “extra” CSS. In this case, instead of using JavaScript to add a class to the page, you can use it to set specific CSS variables:

These changes are picked up by every element in the cascade that uses that variable. Your styles stay cleaner and you don’t have to go through the middleman of applying classes.

Better than Sass: media queries

In Sass, redefining variables within media queries is something that you Just Can’t Do. For instance, maybe you want to swap link colors when you get to a breakpoint. You may be tempted to redeclare the variables themselves inside of the media query:


This, sadly, doesn’t work in Sass, since Sass is a preprocessor and can’t know anything about the conditions under which its output is used.

This pattern can be used with CSS variables, though:


This works with CSS variables because all change is happening in-browser, and the variables do know about the conditions under which they are being used.

This said, I ❤️ Sass and a combination of these tools is way more powerful than each is individually. In fact, I have a great lil mixin further down the page that leverages Sass for declaring CSS variable fallbacks.

Browser support

CSS variables have been in Firefox since 2014, in Chrome + Safari since March 2016, and just landed in Edge April 2017! 🎉 (Source: CanIUse.) So the good news is that they’re quite safe; the bad news is that you will need fallbacks for Edge 14- and, naturally, all of IE.

Providing fallbacks

Luckily, the way to provide these fallback styles is the way we have been doing it since time immemorial:


Declare your fallback first and your desired value second, and browsers that support your preferred property will use it. Browsers that don’t, such as IE 11, will still render something acceptable using your fallback value.

Easier fallbacks with Sass

If you’re using Sass, you can automate fallbacks through a Sass mixin. Create a map of your CSS variable names and their values, and then you can look up those values in a mixin that outputs the fallback style and the preferred one.


The above mixin is used like so:


and outputs the following CSS:


This way, if you change --primary or its fallback, you only need to edit the $vars map and your styles everywhere will update.

Please note that you still need to declare your CSS variables somewhere. If you want all of your variables to be available everywhere, you can use more cool Sass to automatically add all the ones in your map to body or html ✨f you still haven’t had enough of CSS variables, check out

If you still haven’t had enough of CSS variables, check out this Google Developers blog post. They do a great job of sticking to the “CSS variables are custom properties” paradigm.

Now go forth and style!