Blog>>Software development>>Frontend>>CSS vs. SCSS variables — main differences and use cases

CSS vs. SCSS variables — main differences and use cases

This isn't going to be an article about the latest hot new feature. Both CSS and SCSS variables have been around for a long time. SCSS introduced variables in version 2.0 of SASS, released in 2010, and in CSS you’ve been able to use them since CSS3, all the way back in 1999. That being said, these are still powerful tools that can be used to complement each other. Let's talk about the similarities, differences and possible use cases.

CSS basics

CSS stands for Cascading Style Sheets. It is a scripting language used to design and style web pages. CSS is an important web-based technology, used to control the styles of web pages and applications, recognized by the World Wide Web Consortium (WC3) along with HTML (which controls the structure of websites). 

Services Frontend development

CSS code

In CSS, variables, also known as `custom properties` are declared using the `--` symbol followed by a name and a value, like this:

--primary-color: #c0d111;

This declares a variable called `--primary-color` and assigns it a value of `#c0d111`.

You can then use the variable throughout your style sheet by calling its name, wrapped in `var()` function syntax, like this:

color: var(--primary-color);

This will output the value of the `--primary-color` variable in place of the variable name.

CSS variables are scoped element-wise, meaning you can reach them in the element where they were declared or in any of its children. This characteristic can be very useful but can also cause serious debugging problems, so it's important to choose names as specific as possible - the generic `--color` might be used anywhere, would be hard to spot and easy to override, while `--badge-rectangle-hovered-text-color` clearly shows its purpose and origin.

CSS variables can be used exclusively as a whole - there's no way to extract anything from them, they can't also be interpolated, so providing a color, you must pass the whole string. Here’s an example of CSS code that won’t work

primary-color: #c0d;

color: var(--primary-color) + 111; // don't do that

Here’s an example of code that will work:

--primary-color: #c0d111;

color: var(--primary-color); // will work

SCSS basics

SCSS stands for Sassy CSS or Sassy cascading style sheets. “SASS” means Syntactically Awesome Style Sheets, a preprocessor scripting language that is then compiled into a CSS file. It adds functionalities that simplify and streamline the styling process. SCSS accepts any valid CSS syntax but with the added benefits of advanced features that makes writing CSS code easier and more efficient.

SCSS code

SCSS variables are declared using the `$` symbol followed by a name and a value, like this: 

$primary-color: #007bff;

This declares a variable called $primary-color and assigns it a value of #007bff.

You can then use the variable in two ways - if it's a simple substitution you can use it as it is, so:

But here's where the fun begins! You can use interpolation syntax - `#{}` - and inject not the value but the string stored under the variable name and join it with another string. You can use it to create a selector name, like classes, or do what's impossible with CSS variables:

$primary-color: #007;

color: #{$primary-color}bff; // the result is #007bff

SCSS variables are block scoped, which means they're available inside the parenthesis where they were declared. Of course you can also import them using SCSS *@import*, but by default they're encapsulated and unreachable from outside the file.

SCSS vs. CSS - main differences

I've already mentioned some of the main differences between both species of variables - scope and ability to interpolate. But there are more. 

SCSS variables are, just like the rest of SCSS code, compiled into a CSS file, while CSS variables are natively supported by modern browsers and do not require compilation. This might be important during debugging, as you can check CSS variables with browser dev tools, while when using SCSS variables, dev tools will show only substituted values.

Another important difference is the possibility of providing fallback values for CSS variables. You can simply pass it as a second parameter when consuming such a variable:

color: var(--primary-color, red);

Fallback will work if the given variable is not defined, as above, but it may be a trap! Consider the following example:

--primary-color: 10years;

color: var(--primary-color, red); // fallback won't work

The only thing that's evaluated before using the fallback value is the existence of a given variable, not if it's a valid value for the given CSS property or even any valid CSS value.

The next big difference is IDE help when it comes to missing variables. While missing an SCSS variable will cause an error, CSS won't give a hint that something might be wrong. That can be very dangerous, especially when working in a big team. Every member must be aware of this hazard and be very cautious when removing any CSS custom property declaration.

As you can see, CSS variables are powerful but dangerous. We'll discuss later on how to use these features for good.

SCSS and CSS variables use cases

Design system

One of the most obvious use cases for CSS/SCSS variables (in this case, both are equally good in my opinion, but SCSS would require importing) is the maintenance of a design system. It's easier to keep all colors, for example, in one place, and if you have to change one of them, you don't need to check everywhere in your components. It's a must-have in any app bigger than `Hello World!`.

Dependent values

Another important use case might be a situation in which you calculate values, even inside one component. Let's say you have a box and a title that should be positioned absolutely 10px below the box.

.box {

--box-size: 30px;

  $box-size: 30px;

  width: var(--box-size);

  height: var(--box-size);

  position: relative;

}

.title {

  position: absolute;

  top: calc(var(--box-size) + 10px);

}

If anytime in the future you find yourself changing the `.box` size, the `.title`'s position is going to adjust automatically. Note that this example wouldn't work, as it's declared in the other code block.

top: calc($box-size + 10px);

Animations

One of the most widespread use cases for CSS variables is connected with animations. Just as with dependent values, sometimes it's easier to base the whole animation on one value, let's say transition from 0 to 1, and under the hood, use this value to calculate some actual CSS. For example, we might want to transform a box on hover: rotate it, make it wider but lower and - why not? - round the corners a bit:

Thanks to CSS variables we need to change only one property, instead of the four that we want to animate:

.animation:hover {
  --animation-factor: 1;
}

Of course we need a proper setup:

.animation {

--animation-factor: 0;

  width: calc(100px + 100px * var(--animation-factor));

  height: calc(100px - 50px * var(--animation-factor));

  rotate: calc(var(--animation-factor) * 30deg);

  border-radius: calc(10px * var(--animation-factor));

}

SCSS variables can't be used dynamically as they are compiled by bundler and the browser sees only their values.

Component library

CSS variables might be a way to expose an API for styling components if you're creating a components library. Let's say we want to create a `Button`. Let's omit HTML and JS and focus purely on styling.

.library-button {

  background: var(--library-button-background-color, var(--library-button-secondary-color, transparent));

  border-color: var(--library-button-border-color, var(--library-button-primary-color, transparent));

  color: var(--library-button-background-color, var(--library-button-primary-color, inherit));

  border-radius: var(--library-button-radius, 3px);

  padding: var(--library-button-padding, 5px 10px);

  cursor: pointer;

  border-style: solid;

}

If we don't pass any styling to the component, it would be just a reset button:

Fig.1: A component with no styling
css vs. scss variables styling

But it's enough to pass some of them, to have a nicely-styled one. Let's say we want border and text to be the same color and the background to be opaque:

style="--library-button-primary-color: red; --library-button-secondary-color: rgba(255, 0, 0, 0.2)"

and we have some styling:

css vs. scss variables - styling

As you probably noticed, thanks to using fallbacks, we are free to decide if we want to use a "general" style for both font and border, or to separate them by using specific values, like this:

(...)--library-button-border-color: rgb(180, 0, 0) (...);

which results in different colors for text and border:

css vs. scss variables - styling

Hacks

CSS variables might just save the day when things get tricky. I had a task where I was expected to create a component that would have different styles on parent component hover and could be used in any component. Of course, you could do it with JS, but I don't like handling CSS issues with JS, so I decided to combine the powers of CSS properties with SCSS mixins, coming up with something like this:

Component styles:

.tricky-component {

  border: 1px solid var(--tricky-component-hovered-border, var(--basic-border-color));

  background-color: var(--tricky-component-hovered-background, var(--basic-background-color));

  color: var(--tricky-component-hovered-text, var(--basic-text-color));

}

Please note, that the variable names are intentionally verbose, to avoid possible overlapping!

Mixin to be used in parent:

@mixin trickyComponentHover {file

--tricky-component-hovered-background: var(--background5);

--tricky-component-hovered-border: var(--border5);

--tricky-component-hovered-text: var(--primary-outline-text);

}

With the above setup, in the parent component's styles it's enough to add the following rule:

&:hover {

  @include trickyComponentHover;

}

It would also be possible to achieve with SCSS variables but would require importing SCSS files to make variables in scope. With CSS custom properties we got it for free.

Summary

We've walked through the main differences between CSS and SCSS variables including compilation (SCSS variables are compiled into CSS, while CSS variables are natively supported), debugging (CSS variables can be checked in browser dev tools, while SCSS variables show only substituted values), and the ability to provide fallback values (CSS variables can have fallback values, while SCSS variables do not).

The text also mentions various use cases for CSS/SCSS variables, such as in design systems, for dependent values, in animations, for component libraries, and for solving tricky scenarios. CSS variables can be used to calculate values, create dynamic animations, expose an API for component styling, and overcome certain challenges.

Overall, CSS and SCSS variables provide powerful features that can enhance the flexibility and maintainability of style sheets and component libraries, but as with any other feature, must be used with consideration for side effects and possible difficulties.

Skrzeczyński Sławomir

Sławomir Skrzeczyński

Frontend Engineer

Sławomir Skrzeczyński is a Frontend Engineer with three years of professional experience in crafting intuitive and dynamic user interfaces. Before transitioning into the tech industry, Sławomir honed his keen eye for detail and aesthetics as a professional photographer. This unique background fuels his...Read about author >

Read also

Get your project estimate

For businesses that need support in their software or network engineering projects, please fill in the form and we'll get back to you within one business day.