Thursday, March 28, 2024

A Guide to Using CSS Variables

A Guide to Using CSS Variables

Web designers accustomed to using CSS preprocessors are no strangers to CSS variables, but for those of us who are not, CSS variables are now officially part of the CSS specification. CSS variables, or more accurately, as they are called in the spec, CSS custom properties, can be useful for reducing repetition as well as for achieving runtime effects like theme switching. In this tutorial, we’ll be learning how to use CSS custom properties in our web pages.

Declaring and Using CSS Variables

Variables should be declared within a CSS selector that defines its scope. For a global scope you can use the :root or body selector. The variable name must begin with two dashes (–) and is case sensitive, so “–main-color” and “–Main-Color” would define two different custom properties. Other than these two hard rules, the allowed syntax for custom properties is actually quite permissive. Nevertheless, you would be well advised to follow the standard language naming convention of CSS: use dashes to separate the words in the property name.

The following CSS rule declares a custom property of global scope named “–main-color”, It has a value of “#06c”:

:root {
  --main-color: #06c;
}

To reference the variable, use the var() function. It retrieves the custom property value, so that it may be assigned to the property (#06c in this case). So long as the custom property is defined somewhere in your stylesheet and has a scope that includes the target element(s), it should be available to the var function.

#header h1 {
  color: var(--main-color);
}

Variables and Cascade Rules

Custom properties cascade much in the same way as rules, so you can define the same property at different levels of specificity:

/* default color */
:root { --color: blue; }
div { --color: green; }
.myclass { --color: red; }
/* applies the --color property at all the above levels */
* { color: var(--color); }

Here is some HTML markup that shows the effects of the above rules:

<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div class="myclass">
  While I got red set directly on me!
  <p>I'm red too, because of inheritance!</p>
</div>

…which is displayed as:

I inherited blue from the root element!

I got green set directly on me!
While I got red set directly on me!

I’m red too, because of inheritance!

More on the var() Function

We’ve already seen how to use the var() function to retrieve the value of a custom property. What I haven’t mentioned is that the val() function accepts a variable number of parameters: fallback values to be used when the referenced custom property is invalid. Fallback values can be a comma separated list, which will be combined into a single value by the function. For example var(--font-stack, "Helvetica Neue", "Helvetica", "Arial", "sans-serif"); defines a fallback of “Helvetica Neue, Helvetica, Arial, sans-serif” once combined.

Shorthand values may also be stored in a variable. Just like regular CSS, properties such as margin and padding are not comma separated, so an appropriate fallback for padding would define them the same way:

/* definition */
div {
  --color: green;
  --pad: 10px 10px 20px 15px;
}

/* usage */
p { padding: var(--pad, 10px 10px 10px) };

The browser inspector confirms that the variable was successfully applied:

css_variables_shorthand_value_in_action.jpg

Combining var() with the call() Function

Very recently, I wrote about the CSS3 calc() function. It, like other CSS3 functions, may include variables in its expression. So, let’s say that you wanted to apply a size factor to the font. You can’t just append the measurement unit to the variable:

/* definition */
:root { --font-size-factor: 2.5; }

/* faulty application - WON'T WORK! */
div > p { font-size: var(--font-size-factor)em; }

However, if we multiply the –font-size-factor by one unit of measurement, we get a valid and usable result:

/* definition */
:root { --font-size-factor: 2.5; }

/* valid application! */
div > p {
  font-size: calc(var(--font-size-factor) * 1em);
}

Accessing Custom Properties in JavaScript

Thanks to the window.getComputedStyle() function, it’s not only easier than ever to access CSS properties from your JavaScript code, but it also works for variables! Here’s some code that fetches the –color property value of a DIV and displays it. Moreover, the CSS property value is reused to set the color of the property value to the very color that it describes!

var elem       = document.getElementById("alert"),
    theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("--color").trim(),
    msgElt     = document.getElementById("computed_style");

msgElt.innerHTML = "The alert div's color is \"<span style='color:" + theCSSprop + "'>" + theCSSprop +'</span>".';

…which would output something along the lines of:

The alert div’s color is “red“.

You can also set the value of an existing one at runtime, using the setProperty() method of the CSSStyleDeclaration object. Here’s some code that calls the function from a button click:

//HTML
<p><button id="change_doc_color" onclick="changeDocColor()">Change document color to green</button></p>

//JS
function changeDocColor() {
    elem.style.setProperty('--color', 'green');
}

Since setProperty() will accept any valid CSS code, the value string may include the var() function as well. That would allow us to predefine our color before using it, in order to perhaps reuse it elsewhere.

//CSS
:root { --color: blue; --new-color: green; }

//JS
function changeDocColor() {
    elem.style.setProperty('--color', 'var(--new-color)');
}

Conclusion

A word of caution, not all browsers support CSS variables at this time. Most notably, Internet Explorer, Opera Mini, and the Android browser don’t recognize them.

Want to try any of today’s examples? they’re all up on CodePen.

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured