CSS custom properties (aka CSS variables)
CSS custom properties (often named as CSS variables) finally landed in latest Chrome and Safari. Here are some benefits when using them instead of CSS preprocessors.
Intro
Here is basic CSS custom properties usage example (they must start with two dashes):
:root { --main-fg-color: #F00; }
div.red { color: var(--main-fg-color); }
At the first glance there seems to be no benefit of using CSS custom properties instead of CSS preprocessors. However, CSS custom properties are more powerful.
Scope
CSS custom properties have same scope as standard CSS:
<style>
:root { --main-fg-color: #000; }
* { color: var(--main-fg-color); }
#d1 { --main-fg-color: #F00; }
#d2 { --main-fg-color: #0F0; }
</style>
<div id="d1">
<p>div 1</p>
<div id="d2">
<p>div 2</p>
</div>
<div id="d3">
<p>div 3</p>
</div>
</div>
Texts div 1
and div 3
will become red and div 2
green. This also means that you can change CSS custom properties based on media queries, user language in browser (using :root:lang(en) {...}
for example), etc…
Fallback
It's possible to create fallback in the case that CSS custom property is not declared. In following case, if --alert-color
is not present, #f00 is used:
.alert { color: var(--alert-color, #F00); }
Calculations
It's possible to use CSS custom propertys in CSS calculations:
:root {
--default-margin: 10px;
--wide-margin: calc(var(--default-margin) * 3);
--bg-color: #ccc;
}
.block { background-color: linear-gradient(to top, var(--bg-color), #fff); }
Changing with JavaScript
Because CSS custom properties can change at runtime, we can also change then with JavaScript:
document.querySelector("html").style.setProperty('--main-fg-color', '#CCC');
Theming
CSS custom properties can reside in a separate CSS file. That means that you can include different files based on user preference and change how your site looks and feel.
Supported browsers
- Firefox since version 31 (July 22, 2014)
- Chrome since version 49 (March 2, 2016)
- Safari version 9.1 (March 21, 2016) - iOS 9.3
- IE/Edge: no support at all, status is "Under Consideration" for Edge
For more details visit caniuse. As usual, we must wait for Microsoft.
PostCSS plugins
There are two PostCSS plugins that can transform CSS custom properties into CSS that is usable with browsers that do not support CSS custom properties. Both plugins have option {preserve: true|computed}
that do not remove your CSS custom properties from output, so you can use them in browsers that do support CSS custom properties.
postcss-custom-preperties is official PostCSS plugin. It's limited only to :root
selector and can not transform var()
in media queries or selectors.
postcss-css-variables claims to do more, however if you try some transformations in their playground you can see limitations. Try this CSS as input:
:root { --main-fg-color: #000; }
* { color: var(--main-fg-color); }
#d1 { --main-fg-color: #F00; }
#d2 { --main-fg-color: #0F0; }
Result without preservation:
* { color: #0F0; }
Result with preservation:
:root { --main-fg-color: #000; }
* { color: #0F0; color: var(--main-fg-color); }
#d1 { --main-fg-color: #F00; }
#d2 { --main-fg-color: #0F0; }
In both cases fallback color for browsers that do not support CSS custom properties is last value that we used for --main-fg-color
. Also, there is no fallback color for #d1 and #d3. That is just not possible to implement, because at the context of those plugins they do not know the DOM.
I didn't experiment a lot with any of those plugins, but it looks that if you are aware of their limitations while writing CSS custom properties, they can be useful.