CSS Variables: Access Custom Properties with JavaScript

Warning This article was written over six months ago, and may contain outdated information.

The recent release of Fire­fox 31 brought an imple­men­ta­tion of CSS Vari­ables. Based on that, Daniel Imms wrote an inter­est­ing post, What CSS Vari­ables Can Do That Pre­proces­sors Can’t, where he inves­ti­gates a few use cas­es for native vari­ables over those pro­vid­ed by pre-proces­sors like Sass and LESS (there’s a com­mon argu­ment that CSS vari­ables are unnece­sary as we already have them, and more flex­i­bly, in pre-processors).

In this arti­cle I’m going to expand on Daniel’s arti­cle a lit­tle, show­ing an advan­tage of CSS Vari­ables that he doesn’t talk about in detail: inter­act­ing with them using JavaScript.

Before going ahead, a quick refresh­er / intro­duc­tion to CSS Vari­ables. What’s been defined so far is Cus­tom Prop­er­ties, which allow you to define a new prop­er­ty, scope it to part of the doc­u­ment, and assign a val­ue to it. For exam­ple, the fol­low­ing code defines a cus­tom prop­er­ty called –foo-bar, scoped to the body ele­ment, with a colour value:

body { --foo-bar: #f00; }

The prop­er­ty can now be called lat­er in the stylesheet, and its val­ue will be used as the val­ue of the prop­er­ty its applied to; the result of this code is that the div has a background-color of #f00:

div { background-color: var(--foo-bar); }

So, back to Daniel’s arti­cle. In it he points out two key advan­tages of native over pre-processors:

[They] can change at run­time, allow­ing the imple­men­ta­tion of things like them­ing to be done more ele­gant­ly. They’re also scoped, enabling a vari­able to be changed on only a sub­set of the DOM tree.

In his exam­ples he looks most­ly at the util­i­ty of scop­ing, but the point about being able to change at run­time is equal­ly impor­tant. Ear­li­er ver­sions of the spec defined an API inter­face which allowed you to get and set cus­tom prop­er­ties; this has since been pulled while a new API is devel­oped. In the mean­time, how­ev­er, you can still use the CSSStyleDeclaration inter­face to inter­act with cus­tom properties.

To return to our pre­vi­ous­ly defined vari­able –foo-bar, you could get the val­ue of this through JS by using the getComputedStyle() and getPropertyValue() meth­ods, like so (sug­gest­ed by Cameron McCor­ma­ck):

var bodyStyles = window.getComputedStyle(document.body);
var fooBar = bodyStyles.getPropertyValue('--foo-bar');

But more inter­est­ing­ly, you can set the val­ue through the setProperty() method on the style object:

body.style.setProperty('--foo-bar', newValue);

As a very sim­ple exam­ple, here’s a quick demo show­ing how you could update a range of prop­er­ties with a shared colour val­ue — use­ful, per­haps, for show­ing a live pre­view of a theme change:

[DEMO] Colour change with cus­tom prop­er­ties (Fire­fox 31+ required)

Of course, this is pos­si­ble with­out CSS Vari­ables — but it’s eas­i­er with them: there’s only one val­ue to update and no changes to the DOM. I think inter­ac­tion with JS through an API is a great fea­ture, but sad­ly, CSS Vari­ables face an uncer­tain future — they’ve been pulled from Chrome, and are only list­ed as ‘Under Con­sid­er­a­tion’ in IE.

Thanks to Neil McCal­lion for code aid.

4 comments on
“CSS Variables: Access Custom Properties with JavaScript”

  1. As some­one who uses SVG a lot, I’ve real­ly been wait­ing for CSS vari­ables to be adopt­ed. They allow you to cre­ate reusable SVG icons that can be cus­tomized indef­i­nite­ly through CSS.

    CSS vari­ables would be sim­i­lar­ly use­ful for HTML wid­gets or oth­er reusable code. The wid­get author would define cus­tomiz­able styles using vari­ables (with appro­pri­ate fall­backs). The page author could then define the vari­ables for the wid­get con­tain­er, with­out hav­ing to wor­ry about the actu­al CSS class­es or oth­er selec­tors used in the wid­get — and with­out hav­ing to wor­ry about selec­tor clash­es between dif­fer­ent parts of the page.

    Amelia Bellamy-Royds [September 1st, 2014, 19:48]

  2. Care­ful with those words : “sad­ly, CSS Vari­ables face an uncer­tain future — they’ve been pulled from Chrome […]”

    -> see Tab Atkins Jr. on 2014/02/11 :

    “To make it clear­er to those watch­ing at home, our cur­rent Variables
    impl is pret­ty hacky, and kin­da intru­sive and slow (of the “every­thing
    slows down when you use it” vari­ety). We know rough­ly how to
    imple­ment it faster, but doing it right depends on some oth­er rewrites
    we intend on doing, so we’ll re-add this lat­er when they’re done. 

    This is def­i­nite­ly not a judge­ment on the fea­ture itself. ” 

    Source : https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/ScKw9zYRkBc

  3. It would be a pity if CSS vari­ables don’t get imple­ment­ed by most browsers. It’s not that you can’t do with­out them — we all do, via JavaScript. But it leads to great inef­fi­cien­cies, like inject­ing style attrib­ut­es all over the place. Thanks for an infor­ma­tive article.

  4. Paul: It’s great that Tab is con­fi­dent they’ll be reim­ple­ment­ed, but until I see them back in Chrome, with IE & Safari fol­low­ing, I con­tin­ue to think the future of CSS Vari­ables is uncertain.