Getting started with CSS Custom Properties

Custom properties in CSS are exceptionally useful, not just for tokenising your CSS, but also for abstracting complexity and interactivity into smaller, easier to manage pieces. This short guide will get you up to speed with how they work and how to use them.


Say you’ve got some CSS like this:

Code language
CSS
h1 {
  background: goldenrod;
}

p {
  color: goldenrod;
}

.my-element {
  border: 1px dotted goldenrod;
}

There’s a lot of repetition in there, but how do you improve that with native CSS? You can use CSS Custom Properties—also known as CSS variables—to abstract and tokenise your CSS to make your code more manageable.

Code language
CSS
:root {
  --primary: goldenrod;
}

h1 {
  background: var(--primary);
}

p {
  color: var(--primary);
}

.my-element {
  border: 1px dotted var(--primary);
}

In this tutorial, we’re going to get a grip of the basics of custom properties and learn some of the extremely cool and helpful stuff they can do and how they can help your projects.

The basics permalink

Let’s start right from the top and look at some basics. A custom property is just like a normal CSS property and value pair: a declaration. These declarations are defined inside a CSS rule.

Code language
CSS
:root {
  --text-color: rebeccapurple;
}

What the heck is a :root? It is a pseudo-class which represents the root of the document tree, which most of the time means the <html> element. If you are in a Custom Element, using the shadow DOM, though: the :root will represent the root of the shadow DOM instead of the <html> element.

Once a custom property is defined, you can grab the value of it, using the var() function. This will retrieve the current computed value of the property, which we’ll cover in more detail, later in this tutorial.

With the combination of a declared custom property and the var() function, we can use them in our CSS to apply values, like this:

Code language
CSS
:root {
  --text-color: rebeccapurple;
}

h1 {
  color: var(--text-color);
}

Fallbacks permalink

If a custom property value hasn’t been defined or it is invalid, the initial or inherited value will be used instead. This can result in some pretty lousy looking user interfaces, so a good shout is to provide a fallback to the var() function.

Code language
CSS
h1 {
  color: var(--text-color, royalblue);
}

By passing a second, fallback value, the <h1> will be royalblue if the --text-color custom property has not been defined.

Fallbacks are handy as heck, but they aren’t used by browsers that don’t support custom properties. For the microscopic share of browsers that don’t support custom properties, you can use custom properties as a progressive enhancement, like this.

Code language
CSS
h1 {
	color: royalblue;
  color: var(--text-color, royalblue);
}

We still have to pass a fallback to the var() function because as we just learned, an invalid value—which includes undefined custom properties—will result in the initial or inherited value being used.

Custom properties are computed permalink

Once you set a value for a custom property, it can be changed in context and just like any other declaration—a property and value pair—it will be affected by specificity and the cascade.

Take the first example as a context:

Code language
CSS
:root {
  --text-color: rebeccapurple;
}

h1 {
  color: var(--text-color);
}

If this <h1> was inside an <article> with a class of .colour-change, which has a CSS rule, declaring a value for --text-color: that value would be applied.

Code language
CSS
:root {
  --text-color: rebeccapurple;
}

h1 {
  color: var(--text-color);
}

article.colour-change {
  --text-color: seagreen;
}

This CSS is applied because .article.colour-change has a higher specificity than :root.

You can set custom properties with JavaScript permalink

This ability to contextually override a custom property makes them incredibly useful for interactive states and generally writing less CSS. The previous demo used a toggled CSS class to contextually set a custom property value, but you can also set them inside your JavaScript:

Code language
JavaScript
const article = document.querySelector('article');
const button = document.querySelector('button');

button.addEventListener('click', (evt) => {
  article.style.setProperty('--text-color', 'tomato');
});

The <article> gets the value for --text-color applied in its style attribute, which gives it a way higher specificity than :root.

Wrapping up permalink

This quick intro to Custom Properties has hopefully given you the knowledge and confidence to explore them further. If you want to learn more about them, I recommend the following resources:

Until next time, take it easy 👋


Comments

If you liked this post, you might like these ones, too

  1. Create a responsive grid layout

    Even with no media-queries, we can create a flexible and powerful responsive layout.

    Continue
  2. Use transparent borders and outlines to assist with high contrast mode

    It’s tempting to use a sharp box shadow for focus styles to both remove the default focus ring and to get around sharp outline corners. With this method, you can create problems for Windows High Contrast users, so this quick tip will help you get the best of both worlds.

    Continue

Become a supporter by joining the Piccalilli Membership

For $5 per month, you get access to a private, friendly Discord community, a regular newsletter, huge discounts on courses and free access to all premium tutorials.

Most importantly, by becoming a supporter, you help make as much content, free-to-everyone as possible on this site, which benefits everyone. As a member, you also get an ad-free experience around the site.

Support Piccalilli by becoming a member

Sign up for updates

Stay up to date with updates from Piccalilli. You’ll get alerted as soon as any new content gets published. You’ll also get updates on upcoming courses and membership features! You can unsubscribe at any time, too.