CSS variables are entities defined by CSS authors that 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 color might be used in hundreds of different places, requiring global search and replace if that color 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 other contexts.
CSS variables are subject to the cascade and inherit their value from their parent.
Declaring a variable:
element { --main-bg-color: brown; }
Using the variable:
element { background-color: var(--main-bg-color); }
Let's start with this simple CSS that applies the same color to elements of different classes:
.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 reduce the need for 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.
Custom properties do inherit. This means that if no value is set for a custom property on a given element, the value of its parent is used. Take this HTML:
<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:
class="two"
element: 10px
class="three"
element: 2em
class="four"
element: 10px
(inherited from its parent)class="one"
element: invalid value, which is the default value of any custom propertyKeep in mind that these are custom properties, not actual variables like you might find in other programming languages. 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.
Using the var()
function, you can define multiple 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. The function only accepts two parameters, assigning everything following the first comma as the second parameter. If that second parameter is invalid, such as if a comma-separated list is provided, the fallback will fail. For example:
.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" */ }
Including a custom property as a fallback, as seen in the second example above, is the correct way to provide more than one fallback. The technique has been seen to cause performance issues as it takes more time to parse through the variables.
Note: The syntax of the fallback, like that of custom properties, allows commas. For example, var(--foo, red, blue)
defines a fallback of red, blue
— anything between the first comma and the end of the function is considered a fallback value.
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.
When the browser encounters an invalid var()
substitution, the initial or inherited value of the property is used.
Consider the code snippet below.
<p>This paragraph is initial black.</p>
:root { --text-color: 16px; } p { color: blue; } p { color: var(--text-color); }
As expected, the browser substitutes the value of --text-color
in place of var(--text-color)
, but 16px
is not a valid property value for color
. After substitution, the property doesn’t make any sense. The browser handles this situation in two steps:
<p>
doesn't have any parent with color property. So move on to the next step.The paragraph color will not be blue because invalid substitution is replaced by the initial value, not by the fallback. If you had written color: 16px
without any variable substitutes, then it was a syntax error. The previous declaration will then be used.
Note: While a syntax error in a CSS property / value pair will lead to the line being ignored, using a cascaded value, invalid substitution -- using a custom property value that is invalid -- is not ignored, leading to the value to be inherited.
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);
Desktop | ||||||
---|---|---|---|---|---|---|
Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | |
Basic support | 49 | 15 | 29 | No | 36 | Yes |
var()
|
49
|
15 | 31
|
No | 36 | Yes |
env()
|
No | ? | ? | ? | ? | 11.1
|
Mobile | |||||||
---|---|---|---|---|---|---|---|
Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | iOS Safari | Samsung Internet | |
Basic support | 49 | 49 | 15 | 29 | 36 | Yes | 5.0 |
var()
|
50 | ? | 15 | 31
|
37 | Yes | ? |
env()
|
? | 69 | ? | ? | ? | 11.1
|
? |
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)
© 2005–2018 Mozilla Developer Network and individual contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables