What is wrong with universal CSS selector (*) ?

Several people on the web have discouraged using the CSS universal selector (*).  Here’s a little more detailed explanation as to why using it  can create performance issues.

It’s not that your web page will break if CSS universal selector (*) is used, but it might slow down the rendering of the web page by a few microseconds/seconds depending on your machine’s processing power. Here’s why.

To understand this, it would be good to first figure out how a css rule is applied to the html element by the browser.

How a browser applies a CSS rule?

According to an article on Google Code about  “Optimize Browser Rendering”, CSS rules are applied as follows:

As the browser parses HTML, it constructs an internal document tree representing all the elements to be displayed. It then matches elements to styles specified in various stylesheets, according to the standard CSS cascade, inheritance, and ordering rules. In Mozilla’s implementation (and probably others as well), for each element, the CSS engine searches through style rules to find a match. The engine evaluates each rule from right to left, starting from the rightmost selector (called the “key”) and moving through each selector until it finds a match or discards the rule. (The “selector” is the document element to which the rule should apply.). According to this system, the fewer rules the engine has to evaluate the better.

Similarly Mozilla in a article about  ‘Writing Efficient CSS for use in the Mozilla UI’ says :

The style system matches a rule by starting with the rightmost selector and moving to the left through the rule’s selectors. As long as your little subtree continues to check out, the style system will continue moving to the left until it either matches the rule or bails out because of a mismatch.

Your first line of defense is the rule filtering that occurs based on the type of the key selector. The purpose of this categorization is to filter out rules so that you don’t even have to waste time trying to match them. This is the key to dramatically increasing performance. The fewer rules that you even have to check for a given element, the faster style resolution will be. As an example, if your element has an ID, then only ID rules that match your element’s ID will be checked. Only class rules for a class found on your element will be checked. Only tag rules that match your tag will be checked. Universal rules will always be checked.

So, a browser when loading an HTML page, first creates an internal document tree representing all the HTML elements in the page to display. Then it reads the css rules and starts applying them to the element/s that match the selector specified in the rule. Here it is important to understand how the selector matching if performed, becuase that is what affects the rendering speed.

The browser starts with the innermost element specified in the selector and then proceeds to match the other ancestor elements as mentioned in the selector ( right to left ).

Say, for example for a rule like :

ul li a { color:#f00 }

Probably, first all the ‘a’ elements are searched and selected, then out of  all these ‘a’ elements, elements having a ‘li’ element as parent  are filtered out,then out of these remaining elements, elements  where  ‘li’ elements having ‘ul’ parent element are filtered out and then to these remaining ‘a’ elements, the style ‘color:#f00′ is applied.

css-selector-interpretation-sequence

So the browser is probably built to  first traverse the elements tree to pick up specified elements and then filtering out the unwanted elements to reach the specific element/s. This filtering might require traversing the elements tree again and again. So browsers optimise page rendering speed by reducing the number and depth of tree traversals.

Which also means that if the CSS rules have specific selectors , shorter will be the document tree traversal and faster will be page rendering.

Now lets take another example:

body { height:100% }

In this case, CSS engine will quickly find the ‘body’ element and apply the rule ‘height:100%’ to it. In this case searching is signle pass and rule application is to single element.

Now assume, the html document has 200 elements/nodes in the tree, and this universal selector rule is to be applied:

* { padding: 0 }

Since universal rule matches every element, it would mean visiting all these 200 nodes and applying the rule to all 200 nodes.

Now bear in mind that when a rule is applied to an element, other elements in the page might also get affected, so the page rendering might have to be re-calculated. Thus each rule application adds to time taken to create the page to be rendered.

This means that universal selectors add the maximum overhead in terms of time taken to apply the css rules for rendering the page. This means that of all the rules, rules with universal selectors will most probably take the maximum time to apply, thus slowing down the page rendering each time page loads.

Here’s a comparison of time taken for the rule to apply from most to least:

* { padding:0 } - most time consuming, ul li a { color:#f00 } - medium time consuming, body { height:100% } - least time consuming

Thus it is best to avoid using CSS universal selector and instead aim for as specific rule selector as possible.

Finally, how much time difference  would a CSS universal selector make? A few microseconds or more? Should you borther about it?

Now if you understand that every microsecond adds to each second and then each second adds to each minute, you will still appreciate writing more efficinet CSS rules.

Also it would be good to remember that universal selector was not available in CSS1. It became available in CSS2.

Note:

I am relying on the two articles mentioned above to base my understanding about how the browser applies the CSS styles. But I am still looking for a more technical explanation of the process in Firefox/Opera/Chrome/IE. May be someone who has looked at the exact implementation of the rendering engine. Any hint/comment on this aspect will be greatly appreciated.

Also, it would be great to actually measure the time difference the universal CSS selector makes in each browser.  I am not really aware of any tool that could help find this out.  Anybody knowing how to exactly measure the CSS rule rendering time?

References

Google code artile on ‘How to optimise browser rendering’
[ http://code.google.com/speed/page-speed/docs/rendering.html ]

Mozilla article on ‘Writing Efficient CSS for use in the Mozilla UI’
[ https://developer.mozilla.org/en/Writing_Efficient_CSS#section_6 ]

A brief explanation of CSS Universal selector
[ http://meyerweb.com/eric/articles/webrev/200006a.html ]

Your comments