var()

Function for using custom properties in CSS.

Time to read: 6 min

Briefly

The CSS function var() allows you to substitute custom properties as values for properties.

Example

Declaring a custom property:

        
          
          :root {  --color-cyan: #00ffff;}
          :root {
  --color-cyan: #00ffff;
}

        
        
          
        
      

Using the var() function to substitute the value of the custom property:

        
          
          .button {  background-color: var(--color-cyan);}
          .button {
  background-color: var(--color-cyan);
}

        
        
          
        
      

How to Understand

The var() function returns the current value of the custom property. If it changes, the var() function immediately returns the current value.

How var() works

By passing a custom property to the var() function, the browser moves up the hierarchy of elements in search of the value of the custom property.

It will check if the custom property is set on the current element:

  • If yes, it will substitute it for var() and stop the search.
  • If not, it will move to the parent element and repeat the check.

The browser will keep moving up the parent elements until it finds a value. The last point will be checking for the value in :root. If it’s not there, the var() function will set the value to initial or to a fallback value, if provided.

Let's define a custom property:

        
          
          :root {  --card-color: purple;}
          :root {
  --card-color: purple;
}

        
        
          
        
      

Let's set the background color of the card using the var() function. The color will be purple:

        
          
          .card {  background-color: var(--card-color);}
          .card {
  background-color: var(--card-color);
}

        
        
          
        
      

We change the custom property with .setProperty() in JavaScript:

        
          
          document.documentElement.style.setProperty('--card-color', 'midnightblue')
          document.documentElement.style.setProperty('--card-color', 'midnightblue')

        
        
          
        
      

Now, wherever the background color is set, the var() function will return dark blue.

Open demo in the new window

How To Write It

Basic Syntax

The var() function takes 2 arguments:

  1. The name of the custom property.
  2. A fallback value (optional).

If the custom property referred to by the first argument is invalid, the function will use the second value:

        
          
          .card {  padding: var(--card-padding, 10px);}
          .card {
  padding: var(--card-padding, 10px);
}

        
        
          
        
      

The value of padding will be 10px if --card-padding is not defined.

You can specify multiple fallback values. To do this, you need to pass the var() function with possible values as the second argument:

        
          
          .title {  font-size: var(--font-size, var(--title-font-size, 20px));}
          .title {
  font-size: var(--font-size, var(--title-font-size, 20px));
}

        
        
          
        
      

The value of font-size will be 20px if both --font-size and --title-font-size are undefined.

Fallback Value

Another example, although a bit non-obvious. If the variable --font-size is not defined, the fallback value will be: --title-font-size, 20px. Unfortunately, this is not valid:

        
          
          .title {  font-size: var(--font-size, --title-font-size, 20px);}
          .title {
  font-size: var(--font-size, --title-font-size, 20px);
}

        
        
          
        
      

This is because everything after the first comma is treated as a single value. Thus, as a fallback value, the function will return the value from the first comma to the closing parenthesis.

However, this example is valid. The fallback value will be: 10px, 10px:

        
          
          .navigation {  --translate: var(--my-translate, 10px, 10px);  transform: translate(var(--translate));}
          .navigation {
  --translate: var(--my-translate, 10px, 10px);
  transform: translate(var(--translate));
}

        
        
          
        
      
About value validity
        
          
          :root {  --text-color: 16px;}.element {  color: var(--text-color);}
          :root {
  --text-color: 16px;
}

.element {
  color: var(--text-color);
}

        
        
          
        
      

In this example, the custom property --text-color has a value of 16px, which is technically valid. But when the browser substitutes the value --text-color for var(--text-color), it tries to use the value 16px, which is not a valid value for the property color.

The browser sees it as an invalid value and checks if the color property is inherited from the parent element. If so, it uses it. Otherwise, it sets the value to initial.

Features

The var() function can be substituted as part of a property value:

        
          
          .card {  --border-color: black;  border: 1px solid var(--border-color);}
          .card {
  --border-color: black;
  border: 1px solid var(--border-color);
}

        
        
          
        
      

The var() function also works with shorthand properties: margin, padding, border, background, transform, transition etc.

You can use it to substitute either a single value:

        
          
          .element {  --margin-top: 10px;  margin: var(--margin-top) 10px 20px 30px;}
          .element {
  --margin-top: 10px;
  margin: var(--margin-top) 10px 20px 30px;
}

        
        
          
        
      

Or multiple:

        
          
          .element {  --margin-top-right: 10px 10px;  margin: var(--margin-top-right) 10px 50px;}
          .element {
  --margin-top-right: 10px 10px;
  margin: var(--margin-top-right) 10px 50px;
}

        
        
          
        
      

Limitations

The var() function cannot be used as property names, selectors, or anything else except property values.

For example, the following code incorrectly uses a custom property as a property name:

        
          
          .element {  --side: margin-top;  var(--side): 20px;}
          .element {
  --side: margin-top;
  var(--side): 20px;
}

        
        
          
        
      

You cannot mix a custom property with any other value in this way:

        
          
          .element {  --gap: 20;  margin-top: var(--gap)px;}
          .element {
  --gap: 20;
  margin-top: var(--gap)px;
}

        
        
          
        
      

Instead, you can use this trick:

        
          
          .element {  --gap: 20;  margin-top: calc(var(--gap) * 1px);}
          .element {
  --gap: 20;
  margin-top: calc(var(--gap) * 1px);
}

        
        
          
        
      

Or write the full value in the custom property:

        
          
          .element {  --gap: 20px;  margin-top: var(--gap);}
          .element {
  --gap: 20px;
  margin-top: var(--gap);
}

        
        
          
        
      

Inside Other Functions

It also works with functions like:

calc()

        
          
          .element-1 {  --offset: 50px;  height: calc(100vh - var(--offset));}.element-2 {  --height: 100vh - 50px;  height: calc(var(--height));}
          .element-1 {
  --offset: 50px;
  height: calc(100vh - var(--offset));
}

.element-2 {
  --height: 100vh - 50px;
  height: calc(var(--height));
}

        
        
          
        
      

rgb() and rgba()

        
          
          .element-1 {  --rgb: 0, 0, 0;  color: rgba(var(--rgb), 1);}.element-2 {  --rgb: 0 0 0;  color: rgb(var(--rgb));}.element-3 {  --red: 0;  --green: 0;  --blue: 0;  color: rgb(var(--red), var(--green), var(--blue));}
          .element-1 {
  --rgb: 0, 0, 0;
  color: rgba(var(--rgb), 1);
}

.element-2 {
  --rgb: 0 0 0;
  color: rgb(var(--rgb));
}

.element-3 {
  --red: 0;
  --green: 0;
  --blue: 0;
  color: rgb(var(--red), var(--green), var(--blue));
}

        
        
          
        
      

linear-gradient() and radial-gradient()

        
          
          :root {  --c1: red;  --c2: blue;  --grad: linear-gradient(var(--c1), var(--c2));}.element {  --c1: green;  background: var(--grad);}
          :root {
  --c1: red;
  --c2: blue;
  --grad: linear-gradient(var(--c1), var(--c2));
}

.element {
  --c1: green;
  background: var(--grad);
}

        
        
          
        
      

url()

        
          
          :root {  --url: url("https://example.com/example.jpg");}.element {  background: var(--url);}
          :root {
  --url: url("https://example.com/example.jpg");
}

.element {
  background: var(--url);
}

        
        
          
        
      

But this example will not work because the url() function interprets the structure var(--url) as a URL:

        
          
          :root {  --url: "https://example.com/example.jpg";}.element {  background: url(var(--url));}
          :root {
  --url: "https://example.com/example.jpg";
}

.element {
  background: url(var(--url));
}