CSS variables are entities defined by CSS authors which contain specific values to be reused throughout a document. They are set using custom property notation (e.g. --main-color: black;) and are accessed using the var() function (e.g., color: var(--main-color);) .

Complex websites have very large amounts of CSS, often with a lot of repeated values. For example, the same colour might be used in hundreds of different places, requiring global search and replace if that colour needs to change. CSS variables allow a value to be stored in one place, then referenced in multiple other places. An additional benefit is semantic identifiers. For example --main-text-color is easier to understand than #00ff00, especially if this same color is also used in another context.

CSS Variables are subject to the cascade, and inherit their value from their parent.

Basic usage

Declaring a variable:

element {
  --main-bg-color: brown;
}

Using the variable:

element {
  background-color: var(--main-bg-color);
}

Note: The custom property prefix was var- in the earlier spec, but later changed to --. Firefox 31 and above follow the new spec. (bug 985838)

First steps with CSS Variables

Let's start with this simple CSS that colors elements of different classes with the same color:

.one {
  color: white;
  background-color: brown;
  margin: 10px;
  width: 50px;
  height: 50px;
  display: inline-block;
}

.two {
  color: white;
  background-color: black;
  margin: 10px;
  width: 150px;
  height: 70px;
  display: inline-block;
}
.three {
  color: white;
  background-color: brown;
  margin: 10px;
  width: 75px;
}
.four {
  color: white;
  background-color: brown;
  margin: 10px;
  width: 100px;
}

.five {
  background-color: brown;
}

We'll apply it to this HTML:

<div>
  <div class="one">1:</div>
  <div class="two">2: Text <span class="five">5 - more text</span></div>
  <input class="three">
  <textarea class="four">4: Lorem Ipsum</textarea>
</div>

which leads us to this:


Notice the repetition in the CSS. The background color is set to brown in several places. For some CSS declarations, it is possible to declare this higher in the cascade and let CSS inheritance solve this problem naturally. For non-trivial projects, this is not always possible. By declaring a variable on the :root pseudo-class, a CSS author can halt some instances of repetition by using the variable.

:root {
  --main-bg-color: brown;
}

.one {
  color: white;
  background-color: var(--main-bg-color);
  margin: 10px;
  width: 50px;
  height: 50px;
  display: inline-block;
}

.two {
  color: white;
  background-color: black;
  margin: 10px;
  width: 150px;
  height: 70px;
  display: inline-block;
}
.three {
  color: white;
  background-color: var(--main-bg-color);
  margin: 10px;
  width: 75px;
}
.four {
  color: white;
  background-color: var(--main-bg-color);
  margin: 10px;
  width: 100px;
}

.five {
  background-color: var(--main-bg-color);
}

<div>
    <div class="one"></div>
    <div class="two">Text <span class="five">- more text</span></div>
    <input class="three">
    <textarea class="four">Lorem Ipsum</textarea>
</div>

This leads to the same result as the previous example yet allows for one canonical declaration of the desired property.

Inheritance of CSS Variables

Custom properties do inherit. Which means that if no value is set for a custom property on a given element, the value of its parent is used:

<div class="one">
  <div class="two">
    <div class="three"></div>
    <div class="four"></div>
  </div>
</div>

with the following CSS:

.two {
  --test: 10px;
}

.three {
  --test: 2em;
}

In this case, the results of var(--test) are:

  • for the class="two" element: 10px
  • for the class="three" element: 2em
  • for the class="four" element: 10px (inherited from its parent)
  • for the class="one" element: invalid value, which is the default value of any custom property.

Keep in mind that these are custom properties, not actual CSS variables. The value is computed where it is needed, not stored for use in other rules. For instance, you cannot set a property for an element and expect to retrieve it in a sibling's descendant's rule. The property is only set for the matching selector and its descendants, like any normal CSS.

Custom Property fallback values

Using var() you can define mutiple fallback values when the given variable is not yet defined, this can be useful when working with Custom Elements and Shadow DOM.

The first argument to the function is the name of the custom property to be substituted. The second argument to the function, if provided, is a fallback value, which is used as the substitution value when the referenced custom property is invalid. E.g:

.two {
  color: var(--my-var, red); /* Red if --my-var is not defined */
}

.three {
  background-color: var(--my-var, var(--my-background, pink)); /* pink if my-var and --my-background are not defined */
}

.three {
  background-color: var(--my-var, --my-background, pink); /* Invalid: "--my-background, pink" */
}

The syntax of the fallback, like that of custom properties, allows commas. For example, var(--foo, red, blue) defines a fallback of red, blue; that is, anything between the first comma and the end of the function is considered a fallback value.

This method also has been seen to cause performance issues. It makes browsers render pages more slowly than normal as it takes more time to parse through the variables.

Validity and values

The classical CSS concept of validity, tied to each property, is not very useful in regard to custom properties. When the values of the custom properties are parsed, the browser doesn't know where they will be used, so must therefore consider nearly all values as valid.

Unfortunately, these valid values can be used, via the var() functional notation, in a context where they might not make sense. Properties and custom variables can lead to invalid CSS statements, leading to the new concept of valid at computed time.

Values in Javascript

To use the values of custom properties in Javascript, it is just like standard properties.

// get variable from inline style
element.style.getPropertyValue("--my-var");

// get variable from wherever
getComputedStyle(element).getPropertyValue("--my-var");

// set variable on inline style
element.style.setProperty("--my-var", jsVar + 4);

Browser compatibility

  
Feature Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support 49.0 (Yes) 42 (42) No support 36.0 9.1
  
Feature Edge Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile Chrome for Android
Basic support (Yes) 29 (29) ? ? 9.1 49.0

 

See also