The power of CSS variables

CSS variables are the next big thing and their power is often underestimated. People call them “CSS variables”, which doesn’t describe their actual behavior properly. CSS Custom Properties — as the specification names them — can do much more for you than SASS variables. They’re properties and they cascade like normal properties.

I’ve made a test project to learn more about them and tried not to use any SASS variables at all. Here’re some of the benefits I discovered:

Eliminate redundant styling

The principle you know from functions in programming languages applies to CSS Custom Properties: Define once, reuse often. No need to write the same code over and over again 😌

Before

.button {
display: inline-block;
padding: .5em 1em;
color: white;
}
.button--red {
background: red;
box-shadow: inset 0 0 2px red;
}
.button--blue {
background: blue;
box-shadow: inset 0 0 2px blue;
}

After

.button {
display: inline-block;
padding: .5em 1em;
color: white;
background: var(--color);
box-shadow: 0 0 2px var(--color);
}
.color-red { --color: red; }
.color-blue { --color: blue; }

The new approach brings several advantages:

  • All button styles are now in one place
  • Redundant styling has been removed
  • Color classes can be used for all elements with dynamic colors

You can even define a fallback value for all your buttons 🤘

background: var(--color, black);
box-shadow: 0 0 2px var(--color, black);

Conditional values

Custom properties can be made conditional with @media and @supports. Changing a variable in a conditional rule affects the properties in which you’ve used the variable. It’s the same behavior as in the previous example. Just with conditional rules.

.warning {
display: var(--display, none);
background: red;
}
.warning::before {
content: 'Your browser does not support ' var(--feature) '.';
}
@supports not (display: flex) {
.warning {
--display: block;
--feature: 'CSS Flexbox';
}
}
@supports not (display: grid) {
.warning {
--display: block;
--feature: 'CSS Grid Layout';
}
}

A bridge between HTML and CSS

It’s possible to define CSS Custom Properties in the HTML style attribute to use them in your CSS. Think about an element with a gradient, where the first color is always different. You could apply a gradient using JS or inline styles, but this would either cause a flash of unstyled content or HTML that contains styling.

Before

<!-- HTML -->
<div class="gradient" style="background: linear-gradient(to bottom, red, blue)"></div>
<div class="gradient" style="background: linear-gradient(to bottom, yellow, blue)"></div>
/* CSS */
.gradient {
width: 100%;
height: 100px;
}

After

<!-- HTML -->
<div class="gradient" style="--color: red"></div>
<div class="gradient" style="--color: yellow"></div>
/* CSS */
.gradient {
width: 100%;
height: 100px;
background: linear-gradient(to bottom, var(--color), blue);
}

It’s not only easier to read, it also improves the code quality and clarity:

  • The gradient definition is back in the CSS file where it belongs to
  • Redundant styling has been removed from the HTML

JS controlled variables

CSS Custom Properties can be used in calc() functions to perform a calculation with them. That’s cool, but what if you want more power? JavaScript to the rescue! 💪

JS allows to read and write CSS variables. This gives you all the capabilities of a programming language to generate the content of your variables. It’s so powerful, you can even build a parallax scrolling library with it.

Here’s a demo combing CSS Custom Properties with JavaScript to generate a random gradient on the client-side:

Conclusion

Custom properties are way more than SASS variables. I highly recommend to play around with them in a project. Developing a complete page with them gives you a much better feeling than a simple CodePen experiment. Try to avoid SASS variables to see what you can and can’t do with CSS variables.