A Look at CSS Variables

One of the important new features that are coming to CSS in the future, is support for some form of “variables”. One might wonder how variables fit in with something that is not any kind of scripting language. Why would a CSS need variables? Fact is variables in some form are useful in various situations. Take the case of templates for word processing software. If you have a template for a letter, chances are certain things such as the name of the sender, and receiver are repeated in multiple places. In such cases the word processing software often allows you to enter the value once, and have it reflect in multiple places. This is somewhat like a variable, where you set name="Some Name" and have that value used everywhere. There is a great need for variables in CSS, since quite often the same values for border size, colours, and fonts need to be repeated in multiple places. Take, for example, a website with a green theme, the particular green shade in use will have to be applied to many CSS classes, which goes against the DRY (Don’t Repeat Yourself) principle. Now if you want to change to a slightly different shade of green, you need to go back and change all those values. As you can see there is great need for variables in CSS. There needs to be a way to specify a value once, and have it used in multiple places. The good news is, exactly such a feature is currently being developed for CSS as “CSS Variables Module 1”. With the new CSS module, you can define custom CSS properties, and then reuse them later in your code. While this lets you define values once and use them in multiple places, the way it works is in line with the way CSS works, and is thus very different from the way variables work in most other languages.

Using CSS Variables

Defining a variable in CSS is simple enough; let’s say we that our theme colour is red (or #FF0000) and we want to assign that to a variable, here is how we would do that:

:root { var-theme-colour: #FF0000; } 

Here the name of the variable is theme-colour but it is prefixed with a var- in order to tell CSS that it is a variable. We have defined it for the root element so that it can be used by any element later in the stylesheet. Like all other CSS properties these variables will follow the rules of inheritance defined by CSS. We’ll talk more about this later. Now that we have a variable defined, we should know how to use it elsewhere. Here is how to do that:

div.widget { background-color: var(theme-colour); } 

The above code is telling the browser that it should use the value defined by theme-colour for the background-color. Now you can use it however many times you want in the document, and then all you need to do to change the theme colour everywhere is to change it in this one place. This var() function-style notation also allows for providing a default value. Consider the following case:

div.widget { background-color: var(theme-colour, #FF0000); } 

In the above case, the background-color is being set as the value of the variable theme-colour, however in the case that the theme-colour variable has not been defined or has an invalid value, the second, fallback value will be used. The theme-colour variable could be invalid if it has a value that is not a colour.

Inheritance and Cascading with Variables

Now let’s come back to that issue of inheritance and cascading. Let us first look at it without variables. Here is some CSS code:

div { color: green; } a { color: purple; } h1 { color: red; } 

And here is the HTML code we will apply this to:

<div> div content <h1>unlinked heading</h1> <a href="#">link</a> <h1><a href="#">linked heading</a></h1> </div>

In the above case, what would be the colour of different elements? The “div content” will obviously be green; “unlinked heading” will red; the “link” content will be purple; and the final “linked heading” will also be purple. If we wanted to have the linked heading be red as well, we would have to add:

h1 a { color: red; } 

It would take the value red, since that selector is more specific. CSS variables work the same way, and this might seem confusing. Let’s take the same example. This time with variables:

div { var-theme-colour: green; color: var(theme-colour); } a { color: var(theme-colour); } h1 { var-theme-colour: red; color: var(theme-colour); } 

In this case, what would you expect the colours to be? The “div content” will be green like before; “unlinked heading” will red, like before; the “link” content will be green; and the final “linked heading” will be red. As you can see, even though we are setting the colour of the a tag only once, the colour is different in different cases! The colour is green in case of a link inside a div tag, while it is red while its inside an h1 tag, even though we have only one rule for the anchor tag.

Behind the Scenes

Here is what is happening. When we define the variable theme-colour for the div, that variable, and its value are set for all children of div elements. If the above stylesheet was used in a document that had an a tag outside of a div, its colour would be undefined, since it references the variable theme-colour but that variable has not been defined outside div or h1 elements. In our example, the text directly inside the div is coloured with the value of the theme-colour defined for divs, which is green. The “unlinked heading” is an h1 inside a div, in which case the value of theme-colour defined for the div is overridden by the value defined for h1. For the link inside the div it uses the value of the theme colour inherited from its parent div which is green. In the final case, of the “linked heading” the value of theme-colour is inherited from the parent of the anchor tag, the h1 tag, which defines it as red. Now let’s look at another interesting example:

* { color: var(theme-colour); } div { var-theme-colour: green; } a { var-theme-colour: purple; } h1 { var-theme-colour: red; } 

Here the first CSS rule specifies that the colour for all elements should be the value of the variable theme colour; after that we are defining the theme colour for different elements, and in the final result, each element will be styled according to the value of the theme-colour variable defined by its nearest ancestor.

Conclusion

CSS variables are a powerful tool indeed, and manage to provide the flexibility of variables while staying true to their CSS roots, and the nature of CSS. Although in the above examples we have only used CSS variables with colours, they will work with any valid CSS value, lengths, percentages, gradient definitions etc. Right now CSS variables are far from standard, and not supported properly in any browser. There are still some things about CSS variables that are undecided, such is whether variables should be accessible via a short form like $theme-name instead of var(theme-name) (recently this provision was removed, but it may still be debated), whether they should be case sensitive etc. If you still want to play with them there is support in developer branches of Chrome, but it needs to be explicitly turned on. Also note that while using them in Chrome, you will need to use the webkit prefix, since this feature is still prefixed. So you will need to define variables as -webkit-var-varname: varvalue and use them as -webkit-var(varname);. If you want to learn more about CSS Variables, you can read its specification at the W3 website.

Leave a Comment

Your email address will not be published. Required fields are marked *