After getting comfortable with CSS, you can start to explore the more advanced features that make it easier and faster to write. For example, did you know that CSS variables are a thing?
CSS variables are the next step to take your front-end development skills up a notch. They’ll make your CSS code tighter, cleaner, and easier to edit in bulk. In this post, we’ll cover:
- what CSS variables are
- how to declare a CSS variable
- how to use CSS variables in your code
- inheritance with CSS variables
- scope with CSS variables
- fallback values with CSS variables
- the benefits of CSS variables
Let's get started.
What are CSS Variables?
In computer programming, a variable is a unit that stores an assigned value. Variables are fundamental to all computer programs because they let computers store and manipulate information.
Even though it's not technically a programming language, CSS has its own version of variables. CSS variables, also called custom properties, are a special feature that work a little differently than traditionally written CSS.
Normally when you write a declaration in CSS, you write the property (e.g., background-color) followed by a value (e.g., green). This declaration is assigned to a CSS selector, like so:
Before CSS variables, this was the only way to write declarations. If you wanted something resembling variables in CSS, you would need to use a preprocessing language like Sass (which is incorporated into CSS frameworks like Bootstrap).
However, CSS variables now provide another way to style page elements without an add-on. CSS variables let us create our own custom values so our code is easier to understand and edit. Let’s unpack how to use them.
Declaring CSS Variables
To use a CSS variable, we first need to declare one. CSS variables can take on any CSS value. For this example, we’ll use color values (represented as hex codes) and font families.
To declare a CSS variable, write it inside a rule set like any other CSS declaration. The difference is that the property of a CSS variable always begins with two dashes (--), followed by a name you assign. For example:
Here, I’ve created two custom properties: --main-text-color assigned the hex value #FF7A59 (a nice shade of orange), and --main-text-font assigned the typeface ‘Arial’.
Note that custom property names are case-sensitive. A CSS variable named --main-text-color will be interpreted as a different variable than --Main-Text-Color. It’s a good idea to avoid capital letters in your CSS variable names to prevent confusion.
How to Use CSS Variables
Up to this point, we’ve only created our variables. We haven’t yet assigned them to any HTML selector, so the CSS variables won’t affect anything on the page.
To apply our CSS variables to HTML, we use the var() function. In programming, a function is a section of code that completes a task. Functions are often indicated by parentheses following the function name.
The job of the var() function is to find a particular CSS variable and apply it to a selector. It is written as follows:
... where --css-variable-name is the CSS variable you want to apply.
Continuing with our example, we can apply our CSS variables to a selector like so:
In this code, we use var() twice. First, var() finds the value of the --main-text-color custom property that we made, then applies this value (#FF7A59) to the color of any text inside a <p> tag.
Next, var() takes the value of --main-text-font and applies this value (‘Arial’) to the font-family property of text inside all <p> tags.
When we apply this CSS to HTML, we get this result:
See the Pen CSS variables - example 1 by HubSpot (@hubspot) on CodePen.
Inheritance With CSS Variables
Like with normal CSS, child elements inherit the CSS variable values of their parent elements (as long as the parent value is not overwritten in the child element). Consider the following example:
See the Pen CSS variables - example 2 by HubSpot (@hubspot) on CodePen.
Because we assigned the --main-text-color value to the first div, both its child <h2> and <p> elements inside it inherit this custom variable:
Scope and CSS Root Variables
You might have noticed that in the previous example, I declared my CSS variables with a selector called :root. What does this mean?
When you declare a CSS variable, you also give that variable a scope. A variable’s scope determines where that variable will work based on where you declare it. CSS variables can have either local or global scope.
Local CSS variables only work in the selector they’re created inside. Let’s illustrate this by modifying the above example: What happens if I take the --main-background-color declaration and move it to the #section-1 selector?
See the Pen CSS variables - example 3 by HubSpot (@hubspot) on CodePen.
Since --main-background-color is now declared in #section-1, its scope has been changed. This variable will now only apply to the first div, not the second div. This happens because the --main-background-color variable is “local” to #section-1.
On the other hand, CSS variables that work throughout an entire document are called global CSS variables. We make global CSS variables by writing their rules for the :root selector. :root applies to the topmost element in the HTML document object model, <html>, which contains all other elements in the document.
While you can declare CSS variables in any CSS selector you want, it’s a common practice to declare all or most CSS variables in :root so they will work universally in the document.
Every time you use var(), you must specify a CSS variable inside the parenthesis. You also have the option to write a fallback value, a CSS value that is applied if your CSS variable doesn’t work for some reason, such as a typo somewhere in your CSS, or if the browser is unable to render the value you specify for your variable.
Fallback values are placed within the parenthesis of the var() call after the first argument, the CSS variable name. The two arguments are separated by a comma. A fallback value in our example looks like this:
You can even add multiple fallback values for the same CSS property in case your first fallback doesn’t work. Multiple fallback values are written in a list separated by commas, and are applied in that order:
While optional, a fallback value ensures that some type of styling will be applied in case of an error with your CSS variable.
Why Use CSS Variables?
We’ve learned a lot about how to use CSS variables, but why exactly are they useful? Let's review three key benefits of custom properties: They enable bulk editing, dynamic styling, and better readability.
Imagine this scenario: You’ve just finalized the latest draft of your website, and everything looks great. Then your manager shoots you an email. They love the site, but they’ve asked you to change the light purple color of your backgrounds to something a bit more earthy.
That’s no problem. You just need to find a new color, then open up your CSS files and substitute the purple value in one spot, and another spot...and here...oh, and here, almost missed that one...
“Okay,” you say sometime later, “I got them all. Probably.”
In this scenario, you're forced to deal with a drawback of CSS: If you have one style (e.g., a color, font, etc.) that you want to apply throughout your site, you’ll probably need to write it in multiple places in your code, potentially dozens or even hundreds.
But, what if you want to change the rule? In traditional CSS, you would have to change each instance of the rule in the code. Even with a find-and-replace feature, this process is inconvenient, tedious, and prone to errors.
This brings us to perhaps the biggest benefit of CSS variables: They allow you to apply widespread style changes with minimal edits to the code.
Imagine that one of your brand colors, Seafoam Green (represented by the hex code #93E9BE), needs to be applied to backgrounds, text, and icons across your site. With your new knowledge of CSS variables, you can create a custom property for your shade of green:
Then, apply this value to your desired elements:
If at any point you need to adjust this shade of green, you just need to change your CSS variable declaration.
This change will automatically be applied to all elements given the value var(--brand-green). No more tracking down every instance of the old hex code and changing it.
CSS variables allow us to change page style elements dynamically — in other words, without needing to reload the page.
This ability is especially handy for responsive design. When used in conjunction with media queries (a CSS feature that detects device properties like screen size), CSS variables can make elements adapt to the viewport size.
For example, let’s apply this CSS to a <div> element:
In the :root and div selectors, we specify the width, height, and color for our <div>. The following media query instructs the HTML to change our --div-width value only if the screen width dips below 1000 pixels wide. So, we end up with this:
This effect will apply to any <div> element, and any additional element with the width: var(--div-width) declaration assigned to it.
One last bonus: CSS variables can be written in a way that makes it easier for human programmers to understand. If you just see hex code #93E9BE, you won’t know what color it produces, while --brand-green makes clear the purpose of the variable.
Save time with CSS variables.
Once you’ve mastered the basics of CSS, incorporating CSS variables into your programming vocabulary will save you huge amounts of time. From small tweaks to full-on rebrands, it’s helpful to format your CSS in a way that can be read and modified quickly and smoothly.
Editor's note: This post was originally published in November 2020 and has been updated for comprehensiveness.