Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1002891 of Using CSS variables

  • Revision slug: Web/CSS/Using_CSS_variables
  • Revision title: Using CSS variables
  • Revision id: 1002891
  • Created:
  • Creator: stevemao
  • Is current revision? No
  • Comment link less and sass

Revision Content

{{SeeCompatTable}}

CSS Variables are entities defined by authors, or users, of Web pages to contain specific values throughout a document. They are set using custom properties and are accessed using a specific functional notation var().

Basic usage

Declaring a variable:

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

Using the variable:

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

Problems to solve

When building large sites, authors often face a maintainability challenge. In such websites, the size of the CSS is quite large and a lot of information may be repeated in multiple places. For example, maintaining a coherent color scheme throughout a document implies reusing a few color values at numerous positions in the CSS files. Altering the scheme, whether tweaking a single color or completely rewriting it, therefore becomes a complex task requiring precision, as a single find and replace often isn't enough.

The situation gets worse with CSS frameworks, where changing colors requires editing the framework itself. Preprocessors like LESS or Sass are quite helpful in these situations, but may increase the complexity of the creation system, by adding an extra processing step. CSS variables help by employing some of the low-hanging benefits of a preprocessor, without the compilation overhead.

A second advantage of these variables is that the name itself contains semantic information. CSS files become easier to read and understand: main-text-color is easier to understand than the reuse of #00ff00 throughout the text, especially if this same color is also used in another context.

How CSS Variables can help

In imperative programming languages, like Java, C++, or even JavaScript, the state can be tracked through the notion of variables. Variables are symbolic names associated with a given value that can vary with the time.

In a declarative language like CSS, time-changing values are not common, and the concept of variables is also uncommon.

Nevertheless, CSS introduces the notion of cascading variables in order to help solve the maintainability challenge. This allows for symbolically refering to a value throughout the CSS tree.

What are CSS Variables

CSS Variables currently have two forms:

  • variables, which are an association between an identifier and a value that can be used in place of any regular values, using the var() functional notation: var(--example-variable) returns the value of the --example-variable value.
  • custom properties, which are special properties of the form --* where * represents the variable name. These are used to define the value of a given variable: --example-variable: 20px; is a CSS declaration, using the custom --* property to set the value of the CSS variable --example-variable to 20px.
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)}})

Custom properties are similar to regular properties: they are subject to the cascade and inherit their value from their parent, if not redefined.

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"></div>
    <div class="two">Text <span class="five">- more text</span></div>
    <input class="three">
    <textarea class="four">Lorem Ipsum</textarea>
</div>

which leads us to this:

{{EmbedLiveSample("sample1",600,180)}}


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. It 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.

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.

Browser compatibility

{{CompatibilityTable}}

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support {{CompatVersionUnknown}}{{property_prefix("-webkit")}}
33.0
{{CompatNo}} 34.0[2]
{{CompatVersionUnknown}}[3]
{{CompatGeckoDesktop("29")}}[4]
{{CompatGeckoDesktop("31")}}
{{CompatNo}} {{CompatNo}} 9.1
Feature Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile
Basic support {{CompatUnknown}} {{CompatGeckoDesktop("29")}} {{CompatUnknown}} {{CompatUnknown}} 9.1

[1] Chrome initially implemented this feature using a different syntax, which required to prefix custom property names with -webkit-var- to define them. They could then be used unprefixed within a -webkit-var() function. Additionally, the implementation was hidden behind the Enable experimental WebKit features flag under chrome://flags, later renamed to Enable experimental Web Platform features.

[2] Chrome 34.0 removed this feature due to performance issues.

[3] Chrome added this feature again behind the Enable experimental Web Platform features flag under chrome://flags.

[4] This feature is implemented behind the preference layout.css.variables.enabled, defaulting to false and using the old var-variablename syntax in Gecko 29. Starting from Gecko 31 the preference is enabled by default and the new --variablename syntax is used.

Revision Source

<div>{{SeeCompatTable}}</div>

<p><strong>CSS Variables</strong> are entities defined by authors, or users, of Web pages to contain specific values throughout a document. They are set using custom properties and are accessed using a specific functional notation <code>var()</code>.</p>

<h2 id="Basic_usage">Basic usage</h2>

<p>Declaring a variable:</p>

<pre class="brush:css; highlight:[2]  language-css" data-line="2" data-number="">
element {
  --main-bg-color: brown;
}
</pre>

<p>Using the variable:</p>

<pre class="brush:css; highlight:[2]  language-css" data-line="2" data-number="">
element {
  background-color: var(--main-bg-color);
}
</pre>

<h2 id="Problems_to_solve">Problems to solve</h2>

<p>When building large sites, authors often face a maintainability challenge. In such websites, the size of the CSS is quite large and a lot of information may be repeated in multiple places. For example, maintaining a coherent color scheme throughout a document implies reusing a few color values at numerous positions in the CSS files. Altering the scheme, whether tweaking a single color or completely rewriting it, therefore becomes a complex task requiring precision, as a single find and replace often isn't enough.</p>

<p>The situation gets worse with CSS frameworks, where changing colors requires editing the framework itself. Preprocessors like <a href="https://lesscss.org/">LESS</a> or <a href="https://sass-lang.com/">Sass</a> are quite helpful in these situations, but may increase the complexity of the creation system, by adding an extra processing step. CSS variables help by employing some of the low-hanging benefits of a preprocessor, without the compilation overhead.</p>

<p>A second advantage of these variables is that the name itself contains semantic information. CSS files become easier to read and understand: <code>main-text-color</code> is easier to understand than the reuse of <code>#00ff00</code> throughout the text, especially if this same color is also used in another context.</p>

<h2 id="How_CSS_Variables_can_help">How CSS Variables can help</h2>

<p>In imperative programming languages, like Java, C++, or even JavaScript, the state can be tracked through the notion of <em>variables</em>. Variables are symbolic names associated with a given value that can vary with the time.</p>

<p>In a declarative language like CSS, time-changing values are not common, and the concept of variables is also uncommon.</p>

<p>Nevertheless, CSS introduces the notion of cascading variables in order to help solve the maintainability challenge. This allows for symbolically refering to a value throughout the CSS tree.</p>

<h2 id="What_are_CSS_Variables">What are CSS Variables</h2>

<p>CSS Variables currently have two forms:</p>

<ul>
 <li>variables, which are an association between an identifier and a value that can be used in place of any regular values, using the <code>var()</code> functional notation: <code>var(--example-variable)</code> returns the value of the <code>--example-variable</code> value.</li>
 <li>custom properties, which are special properties of the form <code>--*</code> where * represents the variable name. These are used to define the value of a given variable: <code>--example-variable: 20px</code><code>;</code> is a CSS declaration, using the custom <code>--*</code> property to set the value of the CSS variable --<code>example-variable</code> to <code>20px</code>.</li>
</ul>

<div class="note"><strong>Note:</strong> The custom property prefix was <code>var-</code> in the earlier spec, but later changed to <code>--</code>. Firefox&nbsp;31 and above follow the new spec. ({{bug(985838)}})</div>

<p>Custom properties are similar to regular properties: they are subject to the cascade and inherit their value from their parent, if not redefined.</p>

<h2 id="First_steps_with_CSS_Variables">First steps with CSS Variables</h2>

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

<div id="sample1">
<pre class="brush:css; highlight:[3,20,26,32]">
.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;
}

</pre>

<p>We'll apply it to this HTML:</p>

<pre class="brush:html">
&lt;div&gt;
    &lt;div class="one"&gt;&lt;/div&gt;
    &lt;div class="two"&gt;Text &lt;span class="five"&gt;- more text&lt;/span&gt;&lt;/div&gt;
    &lt;input class="three"&gt;
    &lt;textarea class="four"&gt;Lorem Ipsum&lt;/textarea&gt;
&lt;/div&gt;
</pre>

<p>which leads us to this:</p>

<p>{{EmbedLiveSample("sample1",600,180)}}</p>
</div>

<p><br />
 Notice the repetition in the CSS. The background color is set to <code>brown</code>&nbsp;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.</p>

<div id="sample2">
<pre class="brush:css; highlight:[2, 7, 24,30,36]">
: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);
}

</pre>

<div style="display: none;">
<pre class="brush:html">
&lt;div&gt;
    &lt;div class="one"&gt;&lt;/div&gt;
    &lt;div class="two"&gt;Text &lt;span class="five"&gt;- more text&lt;/span&gt;&lt;/div&gt;
    &lt;input class="three"&gt;
    &lt;textarea class="four"&gt;Lorem Ipsum&lt;/textarea&gt;
&lt;/div&gt;
</pre>
</div>

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

<h2 id="Inheritance_of_CSS_Variables">Inheritance of CSS Variables</h2>

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

<pre class="brush: html">
&lt;div class="one"&gt;
  &lt;div class="two"&gt;
    &lt;div class="three"&gt;
    &lt;/div&gt;
    &lt;div class="four"&gt;
    &lt;/div&gt;
  &lt;div&gt;
&lt;/div&gt;</pre>
</div>

<p>with the following CSS:</p>

<pre class="brush: css">
.two {
  --test: 10px;
}

.three {
  --test: 2em;
}
</pre>

<p>In this case, the results of <code>var(--test)</code> are:</p>

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

<h2 id="Validity_and_values">Validity and values</h2>

<p>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 <em>valid</em>.</p>

<p>Unfortunately, these valid values can be used, via the <code>var()</code> 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 <em>valid at computed time.</em></p>

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{CompatibilityTable}}</p>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari (WebKit)</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatVersionUnknown}}{{property_prefix("-webkit")}}<br />
    33.0<br />
    {{CompatNo}} 34.0<sup>[2]</sup><br />
    {{CompatVersionUnknown}}<sup>[3]</sup></td>
   <td>{{CompatGeckoDesktop("29")}}<sup>[4]</sup><br />
    {{CompatGeckoDesktop("31")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>9.1</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Phone</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatGeckoDesktop("29")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>9.1</td>
  </tr>
 </tbody>
</table>
</div>

<p>[1] Chrome initially implemented this feature using a different syntax, which required to prefix custom property names with <code>-webkit-var-</code> to define them. They could then be used unprefixed within a <code>-webkit-var()</code> function. Additionally, the implementation was hidden behind the <em>Enable experimental WebKit features</em> flag under <code>chrome://flags</code>, later renamed to <em>Enable experimental Web Platform features</em>.</p>

<p>[2] Chrome 34.0 removed this feature due to performance issues.</p>

<p>[3] Chrome added this feature again behind the <em>Enable experimental Web Platform features</em> flag under <code>chrome://flags</code>.</p>

<p>[4] This feature is implemented behind the preference <code>layout.css.variables.enabled</code>, defaulting to <code>false</code> and using the old <code>var-<var>variablename</var></code> syntax in Gecko 29. Starting from Gecko 31 the preference is enabled by default and the new <code>--<var>variablename</var></code> syntax is used.</p>
Revert to this revision