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:
- You don't need a preprocessor to use them. Yeah, this is a valid reason.
- 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.
- They can be used with media-queries to create responsive properties.
- 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:
- How to declare a CSS variable.
- 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;
We just declared a custom property. Here are some things you should note about the syntax of custom properties.
- The name of a custom property must always be preceded by two dashes i.e
--
. - 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)}
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%
}
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);
}
var(--padding)
will be replaced with the 10px 20px
. The actual syntax for the var
function is this:
var(<custom-property-name> [, <declaration-value> ]? )
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")
}
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")
}
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)
}
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)
}
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. :)
Top comments (11)
Oh cool! I didn't know vanilla CSS variables were a thing. Thank you! :)
:)
Great post! 👍
So do you come from future?
Android 62, hu! 😁😉
😂😂😂. Thanks for pointing that out.
Thanks to you, Sarah!
the best thing is
css variables
can be updated at runtime by javaScript 😁Ikr😊😊
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.
great post Sarah
Thank you :)
Good to know but what about production ? say you have 50% customers out of 100 who uses IE ?