loading...
Cover image for Don't miss out on css variables

Don't miss out on css variables

timdeschryver profile image Tim Deschryver Originally published at timdeschryver.dev ใƒป3 min read

At first when I heard of css variables when it was introduced, I was a bit skeptical. Why would anyone use it if there are extension languages as scss, sass, less and stylus. After several years, I started to notice more and more peoples using it, writing about it and talking about it. I was missing out on something... It took a while but after using it here and there, I was hooked. In this post I'll cover what convinced me to explore css variables further and to start using them in projects.

Usage

To declare variables, define them in a selector and prefix the variable names with two dashes (--):

div {
  --bgColor: deeppink;
}

A popular approach is to define variables with the :root selector, this way you're defining a global variable:

:root {
  --bgColor: teal;
}

To use the variables, use the var() function:

div {
  background: var(--bgColor);
}

The var() function accepts a second parameter, which is used as a fallback if the variable has not been declared:

header {
  background: var(--bgColor);
  color: var(--color, beige);
}

The snippets above results in:

Image showing the results of the code snippets

Themes

With css variables, creating a theme becomes simple.

Depending on the body's class we can set the variable to its appropriate value:

body.sunrise {
  --background-color: #fff;
  --text-color: #333;
}

body.sunset {
  --background-color: #333;
  --text-color: #fff;
}

We can then use these variables when we style elements:

html,
body {
  background: var(--background-color);
  color: var(--text-color);
}

If the body's class changes to sunrise or sunset, the css variables will cascade to all of the selectors.
In our case, we'll transition to a light or dark theme:

GIF showing a dark and light theme

JavaScript API

This is, in my opinion, the best part. CSS variables have a JavaScript API to get and set variables.

To get a variable, use the getPropertyValue method:

getComputedStyle(document.documentElement).getPropertyValue('--color')

To get a value from an element, first select that element with querySelector:

getComputedStyle(document.querySelector('h1')).getPropertyValue('--color')

To set a variable value, use style.setProperty:

document.documentElement.style.setProperty('--color', 'red')

To set a value on an element:

document.querySelector('h1').style.setProperty('--color', 'blue')

This API opens up some opportunities to use css variables in a clean way.

I encountered this use case a couple of days ago by David K. in one of his XState demos at https://codepen.io/davidkpiano/pen/zWrRye. He uses css variables to create a selection box when the user drags the mouse across the screen.

The css of the selectbox uses the variables to know the four corners (based on the starting point and the current position of the mouse) of the box:

.selectbox {
  left: calc(var(--mouse-x1));
  top: calc(var(--mouse-y1));
  width: calc((var(--mouse-x2) - var(--mouse-x1)));
  height: calc((var(--mouse-y2) - var(--mouse-y1)));

  color: rgba(255, 255, 255, 0.5);
  background: rgba(0, 0, 0, 0.1);
  border: 2px solid currentColor;
  position: absolute;
  transition: opacity 0.3s ease-in-out;
}

Listen on the mouse events, and update the the mouse points accordingly:

document.documentElement.style.setProperty(
  '--mouse-x1',
  ctx.selectArea.x1 + 'px',
)
document.documentElement.style.setProperty(
  '--mouse-y1',
  ctx.selectArea.y1 + 'px',
)
document.documentElement.style.setProperty(
  '--mouse-x2',
  ctx.selectArea.x2 + 'px',
)
document.documentElement.style.setProperty(
  '--mouse-y2',
  ctx.selectArea.y2 + 'px',
)

GIF showing a drag panel

Ending word

If you are like me and didn't see the usefulness of css variables, or didn't know these existed.
I hope this post opened the door to start exploring their use cases.
I stumbled by accident on the JavaScript API, but this API opened my eyes for their real world usages and I'm looking forward to using and seeing them more in the future.

Posted on by:

timdeschryver profile

Tim Deschryver

@timdeschryver

NgRx team member - Writer for AngularInDepth

Discussion

markdown guide
 

Without CSS variables, DEV probably wouldnโ€™t have themes, and some folks really like their dark mode ๐Ÿ˜„

 

And we thank you and the whole team for these awesome themes ๐Ÿคฉ

 

Where can I toggle the dark mode? I can't find that option(I'm using the PWA version of DEV on my phone).

 
 

There's dark mode? been here since January and never noticed it ๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚. just found it pretty deep in settings, would be nice to have a toggle where its better accessible.

 

CSS variables are great! Support is very good - all modern browsers support them. Well, except we know what browser ๐Ÿ˜…

 

From my point of view it's useless as long as IE11 is still used :(

 

In that case a lot of features are useless. Personally, if it's not absolutely necessary to support IE11 in a project, than I'm not thinking about it :)

Also you can provide (not always) a fallback for IE like this:

:root {
  --foreground-color: #333333;
  --background-color: #ffffff;
}

body {
  background: #ffffff;
  background: var(--background-color);
  color: #333333;
  color: var(--foreground-color);
}

That's a great tip, thanks for sharing!

Unfortunately about 8% of the web users are still using IE11 and other browsers not supporting css vars. It depends on your company's policy if you need to take care about those users or not - we have to :(
Of course - it's good to know about "new" things but using them it's unfortunately other thing.
This fallback is good for simple cases, but if you'd like to change the value of the --background-color using javascript, simply changing the --background-color variable the colors won't change it in IE.

I understand that the fallback I mentioned before is not gonna solve the inability to change CSS variables using JS. It just can be used for simple cases.

It's sad that we still have to support IE11. Microsoft created a burden for the web community. And IE11 is holding back the progress :(

But on the other hand, imagine the day when IE11 will be gone! It's gonna be the biggest worldwide party in the history :D

 

I made a polyfill to target IE11
Maybe someone can use it:
github.com/nuxodin/ie11CustomPrope...

 

Awesome work Tobias! ๐Ÿ‘Œ

 

Great article, definitely learned something new here. I'm still not convinced though - how are variables transferred from one stylesheet to another? Say I scope my CSS for individual components (like in react), does it offer seamless integration like other tools already available?
If I have to edit the styles from JS whenever an event fires, why not go full blown CSS-IN-JS?

 

I'm afraid that I'm not the best to answer these questions, as I'm not really familiar with react and css-in-js.

But you can override css variables from another stylesheet in your own stylesheet, which could be useful.

 

Oh my goodness, I hadn't realized you can access these variables with JS. Thanks for sharing!

 

When I encountered it I had the urge to write about it ๐Ÿ™‚
I'm glad that this post was useful!

 
 

Very nice article. Tnx Tim ... Javascript API was new to me too ...

 

Thanks Frederik, I'm glad you like it ๐Ÿ˜Š

 

My life just changed reading this! Eye opening! I always wondered how to do themes? This answers my questions for sure! And JS API on top of it... I am blown away!

 

Those were exactly my thoughts Theo!
I'm glad you learned something new out of this post ๐Ÿ˜Š

 

It's nice to use it. But I think browser support is still an issue.

 

Zero IE support, for the rest it's looking good - caniuse.com/#feat=css-variables

 

css variables are an excellent feature, but the selectbox example isn't the most useful use case IMHO... one can set those css attributes directly.