DEV Community

Sarah Chima
Sarah Chima

Posted on

An Introduction to CSS Variables

One feature that makes preprocessors like Sass and Less appealing is the ability to use variables with them. Recently, I wrote an article on SASS Variables and explored the how variables can make our CSS a whole lot maintainable. Guess who has the ability to use variables too? Our very own CSS. What this means is that we don't have to use any preprocessor to make use of variables.

In CSS, variables are referred to as custom properties. Typing the word "variables" sometimes is easier than "custom properties" so I'll use them interchangeably throughout this article. This article discusses how CSS variables are declared and used. First, let's understand the problem CSS variables solve.

The Problem

Values tend to be repeated in CSS files to keep the look of an app consistent. These values could be colors or even font-sizes. Remembering such values is not always easy. I mean, it's easier to remember the name of a color than the color code. If such values are stored in variables and can be called by just the name of the variables, life becomes much easier.

Another problem occurs when you want to change these values. Say you've been using a wrong color all along and you want to change all instances of that color. While find and replace might seem to be the perfect solution, it is not always ideal, especially in large CSS files. If the color is stored in a variable, you only need to change it once and it affects all properties where it has been used.

Why use CSS variables instead?
But why CSS variables? Why not just use a preprocessor for it. Here are some reasons:

  1. You don't need a preprocessor to use them. Yeah, this is a valid reason.
  2. They cascade. Unlike in preprocessors, you can set a variable in any selector to set or override the current value. So there is no scope for using CSS variables.
  3. They can be used with media-queries to create responsive properties.
  4. They can be changed at runtime. That means you can use JavaScript to access and manipulate CSS variables.

Now that we have considered all of these, let's see how CSS variables can be used.

Using CSS Variables

To use CSS variables we have to know two things:

  1. How to declare a CSS variable.
  2. How to use a CSS variable.

Let's start with the first.

The Syntax for Custom Properties

The syntax for declaring custom properties is quite straightforward. Here's an example.

    --primary-color: #00AEEF;
Enter fullscreen mode Exit fullscreen mode

We just declared a custom property. Here are some things you should note about the syntax of custom properties.

  1. The name of a custom property must always be preceded by two dashes i.e --.
  2. Custom properties are case sensitive. So --primary-color is different from --Primary-color.

Now that we know that, let's move on to discuss an important feature of custom properties.

The Cascade
Custom properties follow the normal cascading rules, so the same property can be defined or set at the different levels of specificity. It is important to note that custom properties do inherit. So if no value is set for a custom property on a given element, it inherits that of its parent. Look at an example.

    :root { --color: blue}
    div { --color: green}
    p{ --color: red}

    * { color: var(--color)}
Enter fullscreen mode Exit fullscreen mode

In the example above, the div and p element uses the color value re-assigned to the --color variable. Other elements which are not children of the div and p element will use the color of the :root pseudo-class which is their parent.

The cascade is important as it what enables us to set different values for the same variable with media queries. This is not possible with preprocessors. Let's use an example.

    --width: 80%
    @media screen and (min-width: 768px) and (max-width: 1020px) {
        --width: 60%;
    }
    @media screen and (min-width: 1020px) {
        --width: 40%
    }
Enter fullscreen mode Exit fullscreen mode

The variable --width is assigned different values and whenever that variable is used, the appropriate value for each screen size is used. This makes CSS variables extremely useful and aids responsive design. Enough about the syntax, let's move to the part where we actually use it.

Using CSS Variables
To use declared variables, we use the var() function. You might have seen in the first example in this article. What the var() function does is to take a variable and replace itself with the value of that variable. Here's an example.

    --padding: 10px 20px;

    div {
        padding: var(--padding);
    }
Enter fullscreen mode Exit fullscreen mode

var(--padding) will be replaced with the 10px 20px. The actual syntax for the var function is this:

    var(<custom-property-name> [, <declaration-value> ]? )
Enter fullscreen mode Exit fullscreen mode

Where custom-property-name is the name of the already declared variable like --padding in the previous example and <declaration-value> is a fallback value, i.e. a value that should be used if the referenced custom property is invalid. Look at an example below.

    p {
        font-family: var(--primary-font,  "sans-serif")
    }
Enter fullscreen mode Exit fullscreen mode

So if the value of --primary-font is invalid or maybe it was never declared, the fallback font sans-serif is used. It is also possible to use more than one value as fallbacks. These values are separated by a comma. Let's rewrite our previous example.

    p {
        font-family: var(--primary-font, "Lato", "Roboto", "sans-serif")
    }
Enter fullscreen mode Exit fullscreen mode

However in cases of shorthand values, like those used with margin and padding, the comma is not used to separate them. So an appropriate fallback is this:

    p {
        margin: var(--margin, 10px 20px 5px)
    }
Enter fullscreen mode Exit fullscreen mode

There's no need to separate them with commas.

With the Calc() function
Custom properties can also be used with the CSS calc() function, this makes it more fun to use. The calc function is used to perform calculations in CSS. Let's see how it can be used with Custom properties.

    :root {
        --margin: 2rem;
    } 

    div {
        margin: calc(var(--margin) * 2);
    }

    p {
        margin: var(--margin)
    }
Enter fullscreen mode Exit fullscreen mode

Browser Support

Currently Chrome 49, Edge 16, Firefox 42, Safari 9.1 and iOS Safari 9.3 support custom properties.

To find out more about CSS variables, here are some good articles on it.
CSS Variables: Why you should care?
CSS Variablesโ€Šโ€”โ€ŠNo, really!
Why I'm Excited About Native CSS Variables

Got any question or addition? Leave a comment.

Thank you for reading. :)

Oldest comments (11)

Collapse
 
belhassen07 profile image
Belhassen Chelbi

great post Sarah

Collapse
 
sarah_chima profile image
Sarah Chima

Thank you :)

Collapse
 
foresthoffman profile image
Forest Hoffman

Oh cool! I didn't know vanilla CSS variables were a thing. Thank you! :)

Collapse
 
sarah_chima profile image
Sarah Chima

:)

Collapse
 
smontiel profile image
Salvador Montiel

Great post! ๐Ÿ‘
So do you come from future?
Android 62, hu! ๐Ÿ˜๐Ÿ˜‰

Collapse
 
sarah_chima profile image
Sarah Chima

๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚. Thanks for pointing that out.

Collapse
 
smontiel profile image
Salvador Montiel • Edited

Thanks to you, Sarah!

Collapse
 
itsjzt profile image
Saurabh Sharma

the best thing is css variables can be updated at runtime by javaScript ๐Ÿ˜

Collapse
 
sarah_chima profile image
Sarah Chima

Ikr๐Ÿ˜Š๐Ÿ˜Š

Collapse
 
sanjay555 profile image
Sanjayshr

Good to know but what about production ? say you have 50% customers out of 100 who uses IE ?

Collapse
 
facundocorradini profile image
Facundo Corradini

Now that's a great reading!

The variables syntax is extremely weird though... But I got the feeling it's actually a nod to BEM, as CSS variables (unlike pre-procesor variables) really excel at making modifiers. That's actually my favourite feature of CSS vars.

Check this pen out :) codepen.io/facundocorradini/pen/Rx...

There I demonstrate how redefining a variable on a simple class selector (modifier) can influence a dozen properties distributed throughout several selectors. It's literally a single line for what would otherwise take 10, so it's a full order of magnitude drier! :D Any input will be appreciated ;)

Now going back to the OP, there are some things I think needs clarifying:

  • "There's no scope" might be an overstatement. There is no code block scope as SASS would, but DOM inheritance scope instead. Which actually, is great. Generally CSS vars are declared at the :root element (/ the html tag) to make them global, but nothing stops you from declaring them anywhere in the DOM tree.

  • For media queries... remember you can't set up the break points a variables. It might sound silly for some, but I know many has those as SASS variables for whatever reason. CSS vars won't let you do that (I tried, I failed :p), so one more reason to keep our good ol' pre-processors as well.