CSS Variables in Firefox Nightly

As reported by Cameron McCormack, Firefox Nightly (version 29) now supports CSS variables. You can get a quick overview in this short screencast:

You can define variables in a context with a var- prefix and then implement them using the var() instruction. For example:

:root {
  var-companyblue: #369;
  var-lighterblue: powderblue;
}

h1 {
  color: var(companyblue);
}
h2 {
  color: var(lighterblue);
}

Header on page

Subheader on page

This defines the two variables companyblue and lighterblue for the root element of the document which results in (you can try it here using Firefox Nightly):

Variables are scoped, which means you can overwrite them:

:root {
  var-companyblue: #369;
  var-lighterblue: powderblue;
}
.partnerbadge {
  var-companyblue: #036;
  var-lighterblue: #cfc;
}

h1 {
  color: var(companyblue);
}
h2 {
  color: var(lighterblue);
}

Header on page

Subheader on page

Header on page

Subheader on page

Using these settings, headings inside an element with a class of partnerbadge will now get the other blue settings:

Variables can be any value you want to define and you can use them like any other value, for example inside a calc() calculation. You can also reset them to other values, for example inside a media query. This example shows many of these possibilities.

:root {
  var-companyblue: #369;
  var-lighterblue: powderblue;
  var-largemargin: 20px;
  var-smallmargin: calc(var(largemargin) / 2);
  var-borderstyle: 5px solid #000;
  var-headersize: 24px;
}
.partnerbadge {
  var-companyblue: #036;
  var-lighterblue: #369;
  var-headersize: calc(var(headersize)/2);
  transition: 0.5s;
}

@media (max-width: 400px) {
  .partnerbadge {
     var-borderstyle: none;
     background: #eee;
  }
}

/* Applying the variables */
body {font-family: 'open sans', sans-serif;}

h1 {
  color: var(companyblue);
  margin: var(largemargin) 0;
  font-size: var(headersize);
}
h2 {
  color: var(lighterblue);
  margin: var(smallmargin) 0;
  font-size: calc(var(headersize) - 5px);
}

.partnerbadge {
  padding: var(smallmargin) 10px;
  border: var(borderstyle);
}

Try resizing the window to less than 400 pixels to see the mediaQuery change in action.

An initial implementation of CSS Variables has just landed in Firefox Nightly, which is currently at version 29 and after the February 3 merge, in Firefox Aurora. There are still a few parts of the specification which still need to be supported before the can go into the release cycle of Firefox Beta and Firefox. Cameron has the details on that:

The only part of the specification that has not yet been implemented is the CSSVariableMap part, which provides an object that behaves like an ECMAScript Map, with get, set and other methods, to get the values of variables on a CSSStyleDeclaration. Note however that you can still get at them in the DOM by using the getPropertyValue and setProperty methods, as long as you use the full property names such as "var-theme-colour-1".

The work for this feature was done in bug 773296, and my thanks to David Baron for doing the reviews there and to Emmanuele Bassi who did some initial work on the implementation. If you encounter any problems using the feature, please file a bug!

For now, have fun playing with CSS variables in Nightly and tell us about issues you find.

About Chris Heilmann

Evangelist for HTML5 and open web. Let's fix this!

More articles by Chris Heilmann…


46 comments

  1. Brandon

    First of all, congrats on landing this. We’ve been wanting native CSS variables for a long time.

    However, this syntax is really verbose. Would it be too taxing to parse variables of the form found in Less or SASS?

    $foo and @bar are much easier to type and read.

    December 15th, 2013 at 09:29

    1. Chris Heilmann

      Good feedback to give the W3C on the open mailing lists they offer.

      December 15th, 2013 at 12:06

      1. Sebastian Zartner

        Since CSS variables (aka custom properties) work differently than the ones in LESS or SASS, so their syntax can’t be reused.
        Also as far as I saw there were already long discussions about what syntax to choose and they agreed on the “var-” syntax.

        January 8th, 2014 at 06:15

  2. Trans

    W3C strikes again. They are uniquely gifted at creating ungainly and ugly standards when widespread industry practices are already commonly used (less, sass).

    December 15th, 2013 at 10:13

    1. Chris Heilmann

      This is a common knee-jerk reaction to anything that comes out from the W3C it seems. The concept of a “widespread industry practice” is a fallacy. Flash tunnels were the norm, why wasn’t there a element?

      December 15th, 2013 at 12:06

      1. Brian Kardell

        +Trans

        CSS variables do things that preprocessors cannot and vice-versa. There is overlap, but these features will make css better and will lead to things like sass continuing to innovate on top of them. They also open new worlds to things that -use- selectors but are not themselves css. Custom Properties were designed in collaboration with lots of intetests, the maintainer of sass, chris eppstein, was involved and influential – this isn’t where we stop, it’s where we start.

        December 15th, 2013 at 12:51

        1. m_gol

          I’d say, though, that there are many more things that CSS variables can do & Sass ones can’t than vice-versa.

          A build step during development is, as Chris mentioned, an overhead to developers. It hampers productivity that I have to either experiment with CSS in the browser and then re-apply changes to my Sass files or modify Sass files and wait for seconds before the change appears in the browser. I’d like to cut that middleman during development (things like sprites, concatenation, minification etc. are needed but not during development) to have changes reflected instantly. OTH, pure CSS is way too limited for my use cases even during development so I have to live with all that overhead for now.

          December 15th, 2013 at 13:33

  3. doug

    why so verbose?

    December 15th, 2013 at 11:42

  4. Tin Aung Lin

    Cool , this means that we won’t need any css pre-compiler in the future.

    December 15th, 2013 at 11:54

    1. Steve v

      CSS preprocessors do more then variables….

      December 15th, 2013 at 11:58

      1. Chris Heilmann

        Of course they do. A lot of them, all in different ways and as part of a build process. This is what gives them power, but also means overhead for developers.

        December 15th, 2013 at 12:03

        1. Moeed Mohammad

          More overhead for developers is dealing with something that really doesn’t need to exist. This seems like such a waste of time — Your time would be better spend contributing to Sass.

          December 15th, 2013 at 13:36

          1. Chris Heilmann

            Standardisation allows code to be used by everyone. I have yet to see an enterprise company that supports a Sass workflow. This is not about replacement of one technology with another but to evolve the standards we agreed on quite some time ago.

            December 15th, 2013 at 16:21

          2. Robert O’Callahan

            See below; CSS Variables are far more powerful than anything a preprocessor can give you.

            December 15th, 2013 at 17:34

          3. m_gol

            @Moeed
            You got it backwards. Good features found in preprocessors should be standardized. There are many drawbacks to using a preprocessor during development – it takes time, it integrates worse with browser dev tools etc. We should be standardazing primitives that are an established practice.

            Besides, as have been stated repeatedly, CSS variables can do so much more than any preprocessor can.

            December 15th, 2013 at 20:55

  5. cokeboys_run_ny

    I think new variants of CSS cross site scripting attacks are likely now that these could be used as obfuscation methods, and possible new way to evaluate script, other than the existing “expression” and “moz-binding”/etc.

    December 15th, 2013 at 11:56

    1. Chris Heilmann

      Interesting topic to research. The same applies to custom fonts though, and do we want to not have them? Every runtime change is a potential attack point.

      December 15th, 2013 at 12:04

    2. Robert O’Callahan

      No, there is no new way to evaluate script here. Also, you can’t use variables on the property-name side of a CSS rule so they’re unlikely to cause any problems for CSS sanitizers.

      December 15th, 2013 at 17:33

  6. matt

    I look forward to the makeover and you end up with

    var-companyblue: #ff0

    December 15th, 2013 at 13:17

  7. Moeed Mohammad

    Why?

    Sass already does variables and much more, and does so in a more interesting way. This seems totally unnecessary.

    Oh, and the syntax is ugly as balls.

    December 15th, 2013 at 13:34

    1. Chris Heilmann

      Your problem is with the W3C -> www-style@w3.org with subject line “[css-variables] … message topic …”

      December 15th, 2013 at 16:22

    2. Robert O’Callahan

      CSS Variables supports scripted changes to variable values, setting variable values using selectors and media queries (as seen in this article!), and inheriting variable values along the DOM hierarchy. By definition preprocessors can’t do those things.

      December 15th, 2013 at 17:31

  8. Bastian

    What this feature can do, that javascript can’t?

    December 15th, 2013 at 13:41

    1. Doug

      For starters, this is CSS, not JavaScript. However, why would you want to set CSS values in JavaScript? If you’re setting a certain color or size of many elements, are you gonna want to do that in JavaScript?

      December 15th, 2013 at 14:42

      1. Bastian

        Nope. If i want to set any values of many elements in CSS, i will use cascading…

        December 15th, 2013 at 23:49

        1. m_gol

          Cascading won’t help you achieve many goals like having the same color in 100 different places on the site. Unless you’re willing to litter your markup with a huge number of non-semantic classes.

          December 17th, 2013 at 10:01

          1. Bastian

            I agree that this makes things easier, but the cost is that developers will pay even less attention for proper css definitions that today…Im using javascript to create dynamic changes on elements without changing any definitions in css sheets, just basing on classes, id’s, or other values and still being semantically ok. When i started my adventure with web technologies i learn that css sheets were for element’s definitions, and server side programs/ javascript for logic. Now things gonna change. Maybe it has to be like that, some new books need to be wrote then.

            December 17th, 2013 at 10:19

  9. marc fawzi

    The syntax makes me want to puke. It’s meant for machines not humans. This will surely lead to more people opting for the CSS preprocessor route. I can see sass/less outputting this syntax but letting users to use the preprocessors much simpler and more sensical syntax.

    December 15th, 2013 at 16:07

    1. Chris Heilmann

      Sorry to hear about your upset stomach. I am sure there are very sensible reasons why the syntax wasn’t taken over verbatim. Would be interesting to do an interview to find out.

      December 15th, 2013 at 16:19

      1. Marc Fawzi

        Funny. I do have the flu today. I think the negative reaction is mostly because the decisions have not been contextualized.

        December 15th, 2013 at 16:47

  10. Alex

    The biggest issue I see is backward compatibility.

    If my ‘border-radius’ doesn’t render in IE8, no big deal — my pictures just have square corners.

    If I understand correctly, a browser that can’t read this will get a null value for any CSS variable. Like ‘background-color: null’.

    If we include it in browsers, I guess it might be ready for general use in 3 years, but gee, people will have been using Sass, Less for a long time by then, and those workflows will be presumably pretty mature by then.

    Still enjoy seeing stuff like this though. It’s important to try stuff and learn what works. Good work, Chris.

    December 15th, 2013 at 18:57

    1. m_gol

      It won’t get parsed as null (there is no such concept in CSS anyway), the whole rule will just be dropped, it has always been this way in CSS. It’s a cool feature because you can easily degrade:

      background-color: black;
      background-color: var(dark-bg);

      There are other CSS new features that do not degrade gracefully, like Flexbox or grid layout. But the world moves forward.

      December 15th, 2013 at 20:50

  11. poke

    People seem to miss that CSS variables have very different semantics than preprocessor variables. CSS variables are scoped by the DOM tree; the actual value of a variable can only be evaluated for elements in the DOM on a case-by-case basis. This makes them very powerful. As shown in the article, the values can be even changed based on media queries which is an incredible feature.

    None of this can be done by preprocessor variables. Those are simple variables with a scoping limited to selector nesting. They are processed _once_ and cannot be affected at run-time later. You can think of then as a simple search and replace.

    Both kinds of variables are useful; CSS variables open up a whole new range of possibilities, so they are definitely worth implementing. But because they work so differently, having a completely different syntax makes a lot of sense, so they will not be mixed up with variables known from programming languages or preprocessors. The CSS property-like syntax makes this pretty clear and in my opinion gives a quite simple idea of their semantics too: They are custom CSS properties (prefixed with var-) that are inherited like every other CSS property, and which can be cross-referenced using the var function.

    December 15th, 2013 at 20:42

    1. Jérémy

      Finally an intelligent comment about that !

      Thanks

      December 16th, 2013 at 01:10

  12. Niloy Mondal

    Congratz to Firefox for being the first to implement this.

    December 15th, 2013 at 23:28

    1. Tim

      Actually, Chrome has that implemented for a while already, it’s just hidden behind a about:flags flag (Experimental CSS platform features flag I think).
      But yeah, it’s a great thing that Firefox implements it.

      December 16th, 2013 at 12:12

  13. l2aelba

    .parent {
    color:#fff;
    .children {
    color:#000;
    }
    }

    This is I waiting for (in native CSS)

    December 16th, 2013 at 01:04

  14. Brian Knapp

    While we’re making changes, there are several features of Kivy’s kv language for specifying data-binding and widget tree’s that are quite a painful point whenever I return to web programming without them.

    * Properties are able to be subscribed to. Just data-binding.
    * Properties can be set to expressions akin to some CSS compiling toolchains.
    * Expressions can contain properties and the entire expression will be re-evaluated if any properties in it change, essentially creating data-flow behavior.
    * CSS rules can be set to expressions that update via data-flow.
    * Data structures can be injected into the CSS namespace to allow controllers and other objects from JS space to be used in both the CSS expressions and JS.
    * Prototypes for Widgets and Layouts (from Widget) that allow nesting of essentially templated HTML and specification of a Widget tree using these higher-level widgets instead of div soup. The HTML elements are the analog to Kivy graphics instructions and etc function the same as mundane Image Widgets.

    This stuff is so good in Kivy that I really have developed an apprehension towards web in the bowels of my soul or possibly near my appendix. I really don’t know how to like web programming at all without some drastic changes to meet other UI programming paradigms.

    Basically I’m asking to throw out the baby and the bathwater in order to replace it all with exactly what I’ve grown familiar with, but it is almost Christmas and Santa is my preferred deity. All hail Santa. We Worship the Santa.

    December 16th, 2013 at 16:35

    1. Robert Nyman [Editor]

      Feel free to suggest those ideas to W3C, and if there’s an uptake, they will be standardized.

      December 17th, 2013 at 04:19

  15. abs

    Standarization of css variables is something that I am waiting for years. Congratulations to mozilla for this step. By the way, I also think that this way is so verbose.

    December 16th, 2013 at 18:52

  16. Vishnu Haridas

    Y U NO standardize this yet? All the web developers in this universe are waiting for it!

    December 19th, 2013 at 10:06

  17. Alex Bell

    Is “var” really that much more verbose than “$”? It’s certainly vastly more semantic, and there’s a much deeper historical precedent for it. Also, as has been pointed out, the “live” DOM scoping is totally different from anything in SASS. I think the W3C actually got this pretty much right all around. Cheers!

    December 19th, 2013 at 11:37

  18. David Baughman

    SASS, LESS, MOAR! Rabble rabble rabble…

    Let’s be honest, it’s not fair to compare a preprocessor to CSS itself. There are loads of things you can do with a pre-processor that probably won’t ever be part of the core CSS spec. Also, preprocessors can make functional updates a lot more regularly than changes to the spec are possible. So if you want to ride the wave of the latest and greatest, stick with pre-processors. If pre-processors scare you, then you’re getting a nice little Christmas present this year in the form of variables =)

    That said, these updates should make the job of pre-processors easier. Who knows, maybe the compiled CSS file from LESS/SASS will be smaller as a result.

    December 19th, 2013 at 12:51

  19. Daniel

    Hideous syntax. :(

    December 20th, 2013 at 08:11

  20. Jonathan Prates

    Why not?

    :root {
    companyblue = #369;

    I think that = is best than var- to represent an assignment.

    December 28th, 2013 at 13:39

  21. Alex

    I’m glad they are going in this direction, it was about time. I wish the syntax was more elegant.

    December 30th, 2013 at 06:59

Comments are closed for this article.