DEV Community

Cover image for Magic of CSS + SASS variables
Sumit Sharma
Sumit Sharma

Posted on

Magic of CSS + SASS variables

Css and Sass variables are very powerful on their own. But when you use them in combination, they do wonders.

But as our project grows, we tend to define as many variables as required. And with the current trend and requirements(like Dark Mode), people are preferring CSS variables more because of their dynamic nature (can be updated in Runtime).

We even tend to define different variables for shadows and opacity requirements.

The problem starts when you try rgba()

Problem Statement

  1. Use any opacity variant of any of the brand colors without adding complexity.
  2. Apply changes to any brand color by editing just one line of code.
  3. Fully utilize the power of dynamic CSS Variables.

The normal way

$primary: #03A87C;
.block{
    background-color: rgba($primary, .5);
}

We could hand a HEX value to the rgba() function and Sass would convert it to a set of rgb values, then spit it out in rgba() syntax with my specified opacity:

.block{
    background-color: rgba(3, 168, 124, .5);
}

This was incredibly useful because I could generate any shade of a core color I needed, depending on my contextual use case. The only problem is, I have to be using Sass. CSS can't do that…or so I thought.

:root{
    --primary: #03A87C;
}
.block{
    background-color: rgba(var(--primary), .5);
}

The example which used a CSS variable failed. Using SASS's rgba() function with CSS variables fails to be rendered correctly.
According to the official CSS spec, "the values of custom properties are substituted as is when replacing var() references in a property's value".

However, these values are only interpreted at execution time. This means that when SASS was being compiled to CSS, var(--primary) was not interpreted as a color value. Instead, the compiler saw a random string and SASS's rgba() function failed to be correctly compiled.

How you can make this work?

According to the spec, the native rgba() function only accepts 4 comma-separated values as parameters, which means that we cannot use hex color values. Maybe we could try to declare our variables as comma-separated RGB values from the get-go.

:root { 
    --primary-rgb: 3, 168, 124;
}
div { 
    background-color: rgba(var(--primary-rgb), 0.4);
}

This method works !!
You can define two versions of your color, which you can use according to the requirement.

  1. one with hex code
  2. one with rgb() value
:root{
    --primary: #03A87C;
    --primary-rgb: 3, 168, 124;
}
div { 
    background-color: rgba(var(--primary-rgb), 0.4);
}
p{
    background-color: var(--primary);
}

Now, this is a pretty good solution and sure the number of variables would increase in the file but it's a good compromise on simplicity to make our solution work.

However, with this method, two new problems arose:

  1. A value such as 3, 168, 124 is not very readable: this method would require us to convert all my color values into this format.
  2. We can no longer edit these values in a color picker to test them out. Neither my IDE nor chrome dev tools can recognize these values as colors.

Cherry on the cake

To remove this exercise of manually converting HEX to rgb(), there is a function in SASS.

And Voila !!

@function hexToRGB($hex) {
  @return red($hex), green($hex), blue($hex);
}

:root {
  --primary: #03A87C;
  --primary-rgb: #{hexToRGB(#03A87C)};
}

Finally to not repeat the HEX values, assign them a variable

@function hexToRGB($hex) {
  @return red($hex), green($hex), blue($hex);
}
$primary: #898DF8;
:root {
    --primary: #{$primary};
    --primary-rgb: #{hexToRGB(#03A87C)};
}
.block{
    background-color: rgba(var(--primary-rgb), .3);
}

And now a working Codepen solution

https://codepen.io/Sumitss92/project/editor/XxLVWM

Top comments (0)