DEV Community

Cover image for Write CSS variables faster in SCSS
Mehdi M.
Mehdi M.

Posted on • Updated on

Write CSS variables faster in SCSS

Update (October 20th, 2022): while this helper remains cool, I have decided to not use it outside of personal projects. Compared to IDE auto-completion, its benefits might not be worth the cognitive load linked to any additional abstraction.


I love CSS variables (here’s why) but the syntax isn’t very readable to me:

  • there’s this double hyphen thing in the name: --varName;
  • the var function is required to access it: color: var(--myColor);.

Crazy. Let’s simplify this with…

The v() function!

@function v($var) {
  @return var(--#{$var});
}
Enter fullscreen mode Exit fullscreen mode

Usage

First, define your CSS variables normally:

:root {
  --primary: #000;
  --bg: #fff;
}
Enter fullscreen mode Exit fullscreen mode

Then, use it with v(varName).

html {
  background: v(bg);
  color: v(primary);
}
Enter fullscreen mode Exit fullscreen mode

It generates this:

html {
  background: var(--bg);
  color: var(--primary);
}
Enter fullscreen mode Exit fullscreen mode

That’s only a 4 characters win, but it’s a cool one for readability and you’ll use it often.

That’s it!

Optional second parameter as fallback

As it was pleasely mentioned in the comments, the CSS var() function can take a fallback as second parameter: if the wanted CSS variable isn’t defined or has an understandable value for the browser, this default value will be used.

So, let’s update v() accordingly:

@function v($var, $fallback: null) {
  @if($fallback) {
    @return var(--#{$var}, #{$fallback});
  } @else {
    @return var(--#{$var});
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, let’s write something that benefits from the optional fallback, like a “pin the video in a corner” feature:

One small bit of fun

Do you know that -- is a valid name for a CSS custom property? Unfortunately, it’s hard to declare and use it in SCSS. But the v() helper makes your life a bit easier. ✌️

Other attempts that could have been cool, but…

If you’re wondering how to improve my package, I compiled three unsuccessful attempts in a Gist. Feel free to propose CSS variable tips!

Top comments (21)

Collapse
 
jappe999 profile image
jappe999

Can you explain why you use css variables instead of scss variables? What are the benefits of using css variables over scss variables?

Collapse
 
meduzen profile image
Mehdi M.

CSS variables end up being used on the compiled CSS stylesheet. Having CSS variables instead of regular hardcoded values have two benefits:

  • like SCSS variables (or all other languages variables), it enforces consistencies;
  • you can’t redefine SCSS variables once it has been compiled, but CSS variables can be redefined and manipulated in both CSS and JS… and even be use for animations!

SCSS variables are intended to help you during your development process. At the end, there’s nothing wrong about sticking to SCSS variables. CSS variables are cool because they allow to do stuff in an easier way.

Recently, I drafted a before/after image comparison with the help of CSS variables. It’s only like 10 lines of JS.

Nowadays, the only good reason to not use CSS variables (apart from “I have to learn them”, I only did recently) is that legacy browsers (IE 11 and Opera Mini) doesn’t support them.

Collapse
 
bgallagh3r profile image
Brian Gallagher

Thanks for the explanation. I was just about to ask the same question. I've been using SASS for years now and it didn't occur to me about the ability to change CSS variables on the fly, that does make sense now that you've explained it.

I've never had cause to use them so I wasn't entirely sure of the point of having to define them in CSS in the first place.

Collapse
 
jappe999 profile image
jappe999

Nice! Thanks!

Collapse
 
ahmedmusallam profile image
Ahmed Musallam

You should add this to the article as a section titled “but why?”

Thread Thread
 
meduzen profile image
Mehdi M.

Thanks for the suggestion! It took me some times to know where to add it in order to not break the reading flow. I end up putting it in the first sentence as a link to the comment.

Thread Thread
 
ahmedmusallam profile image
Ahmed Musallam

That works good. But i think your comment is specifically regarding favoring CSS variables over SCSS/pre-processed variables.

For me as a reader and someone that is not a css expert, I though “why the hell would you use css variables and make a wrapper around them when pre-processed variables are perfect”

But then I read this comment and it made sense. So I would probably add a section titled “why the heck would you use css variables in SCSS” and link the comment so the reader has context.

Thread Thread
 
meduzen profile image
Mehdi M.

I see what you mean. I'll read again the whole stuff when I'll have some time and reconsider the place of the why explanation. Thanks for your feedback!

Collapse
 
iamschulz profile image
Daniel Schulz

They are different things. Scss vars are compiled into values, CSS vars are properties (they're actually called custom properties), that can be changed in runtime, for example by us or by media queries. That gives you other options for theming.

Collapse
 
vinceumo profile image
Vincent Humeau • Edited

Hey, cool way.

I use a different approach, I set all my scss variables in maps, so I can link them to a function and return the css variables. I have a flag as well in case I want to use the real value.


// In _settings.scss $use-css-var: true;


// ------------------------------
// Sass Variables
// ------------------------------
$variable-prefix: --variable-; // CSS Variable prefix

$variables: (
  val1: 1,
  val2: 2,
  val3: 3 // etc.
);

// ------------------------------
// Set variable function
// ------------------------------
@function myVariable($variable, $true-val:false) {
  @if $use-css-var == true {
    @if $true-val == true {
      @return map-get($variables, $variable); //True Val
    } @else {
      @return var(#{$variable-prefix}#{$variable}); //CSS Var
    }
  } @else {
    @return map-get($variables, $variable); //Disabled CSS Var
  }
}

  // If $use-css-var == true
    // myVariable(val1) => var(--variable-val1)
    // myVariable(val2, true) => 2
  // If $use-css-var == false
    // myVariable(val3) => 3
    // myVariable(val2, true) => 2

// ------------------------------
// Set root variables
// ------------------------------
@if $use-css-var == true {
  :root{
    @each $name, $variable in $variables {
      #{$variable-prefix}#{$name}: $variable;
    }
  }
}

  // Output if $use-css-var == true
  // :root{
  //   --variable-val1: 1;
  //   --variable-val2: 2;
  //   --variable-val3: 3;
  //   /*etc.*/
  // }

vinceumo.github.io/devNotes/sass/2...

Collapse
 
equinusocio profile image
Mattia Astorino • Edited

Can your function be rewritten like this?

@function myVariable($variable, $true-val:false) {
  @if $use-css-var == true and $true-val == true  {
    @return map-get($variables, $variable); //True Val
  } @else {
    @return var(#{$variable-prefix}#{$variable}); //CSS Var
  }
}
Collapse
 
meduzen profile image
Mehdi M. • Edited

I just noticed the title of my article may lead to confusion: it’s more about accessing to the variable once defined, it’s not about the variable definition, which is a topic covered by your article.

What you write reminds me the css-vars package or the postcss-custom-properties plugin, which both seems very similar to what you do.

I’m currently working on a SCSS workflow for Custom Media Queries, this time more on the media query definition. It will leverage the postcss-custom-media and postcss-media-minmax plugins, and from what I’m testing, it’ll be the faster way to both declare and use media queries I’ve ever encounter. (Huge statement. :D)

Collapse
 
briancodes profile image
Brian

Hi. Is it necessary to use interpolation e.g. #{$fallback}, for the fallback? I think it would work without that

Collapse
 
meduzen profile image
Mehdi M.

You’re right, thanks! I opened a PR to make sure not to forget.

Collapse
 
meduzen profile image
Mehdi M.

Merged and it’s even better. \o/

Collapse
 
meduzen profile image
Mehdi M.

Hello everyone,

I turned this function into a small NPM package:

  1. npm install v.scss pulls the package into your project.
  2. @import '~v.scss'; in a SCSS files makes v() available.
Collapse
 
meduzen profile image
Mehdi M.

I added a note about a custom property with a weird name: --.

Collapse
 
meduzen profile image
Mehdi M. • Edited

Yo everyone. I updated the article and the v() to handle the CSS var() second parameter, which is optional. I didn’t even knew its existence. I hope you’ll enjoy the embed Codepen! 🎶

Collapse
 
serkanbektas profile image
Serkan Bektas

sensible way.

Collapse
 
equinusocio profile image
Mattia Astorino

A bit useless since this function doensn’t allows you to pass a fallback chain as the var() do

Collapse
 
meduzen profile image
Mehdi M.

Now it does. 👐