by Steven Bradley
on Monday, October 3rd, 2011
in CSS ::
For the last few weeks I’ve been looking at different css selector patterns. One thing I haven’t mention is the efficiency of the selectors, something Chad commented about on the very first post in the series.
I had originally intended on adding a link or two about selector efficiency in one of the posts, but completely forgot. Instead I’ll offer this post, along with those links I had originally intended on including.
Here are the 3 css selector posts in case you missed any.
- Do You Use These 7 Attribute Selectors In Your CSS?
- How To Use CSS Combinators and Simple Pseudo Class Selectors
- How To Use Structural Pseudo Classes and Pseudo Element Selectors
One thing I should say at the outset is that for most of us what follows probably isn’t going to significantly affect anything on our sites. I’ll talk more about this later in the post, but please know you aren’t likely to see large savings in performance from optimizing your selectors.
How Do Browsers Read Selectors?
This entire discussion is based on how browsers read selectors in order to identify which html gets styled and the key is that browsers will read your selector from right to left.
div.nav > ul li a[title]
A browser seeing the above selector will first try to match a[title] in the html, and then proceed to the left matching li, ul, and finally div.nav.
This last part of the selector (in this case a[title]) is called the “key selector” and it’s ultimately what will determine how efficient your selector will be.
The sooner browsers can filter out a mismatch, the less they have to check and, the more efficient the selector. David Hyatt writing about selector performance for Mozilla tells us:
This is the key to dramatically increasing performance. The fewer rules required to check for a given element, the faster style resolution will be.
Since a selector that fails is more efficient than if the same selector matches we want to optimize key selectors to fail. The more specific the key selector, the quicker the browser find mismatches.
So which type of selector is most and least efficient?
Below is the order of efficiency for selectors. IDs are the most efficient and pseudo classes and pseudo elements are the least efficient.
- id (#myid)
- class (.myclass)
- tag (div, h1, p)
- adjacent sibling (h1 + p)
- child (ul > li)
- descendent (li a)
- universal (*)
- attribute (a[rel="external"])
- pseudo-class and pseudo element (a:hover, li:first)
Looking at the above list we’d prefer our key selector to be an id or class than a child or descendent selector. CSS3 selectors like pseudo-classes and attributes are very useful, but also the most inefficient.
will be more efficient than
because the key selector of the first is more efficient than the key selector of the second.
Adding tags in front of ids and classes also slows thing down and makes the selector less efficient so
are more efficient than
Guidelines from Mozilla
In David’s article he offered some guidelines for writing efficient css selectors, which I’ll present below.
- Avoid Universal Rules
- Don’t qualify ID Rules with tag names or classes
- Don’t qualify Class Rules with tag names
- Use the most specific category possible
- Avoid the descendant selector
- Tag Category rules should never contain a child selector
- Question all usages of the child selector
- Rely on inheritance
- Use scoped stylesheets
You can read his original article for more details. It’s a quick read. It is also over 10 years old. Not that its age invalidates any of the information. Browsers still match selectors from right to left after all.
However a few details like saying descendant selectors are the least efficient should be updated, as there now exist new and less efficient selectors that didn’t exist when the article was written.
Does it Matter?
This is all well and good, but does any of it matter? Should you rewrite existing stylesheets to make your selectors more efficient? If ids are the most efficient selector should you start adding ids to every html element in your document?
Probably not. For one there’s a balance between writing semantic code and writing code for improved performance. There are advantages to both semantics and performance and we shouldn’t choose one entirely over the other.
Second selector efficiency and inefficiency probably isn’t going to impact most sites all that much.
We’re not talking a difference of several seconds from most to least efficient. We’re talking about milliseconds in the worst case. For the majority of sites you aren’t going to notice a difference and the effort likely outweighs the savings.
That said a large site that generates a lot of traffic probably will see a difference and it might very well be worth the effort to optimize selectors.
It also makes sense to understand how this works and be more efficient in general For example knowing that
is more efficient than
why would you add the tag in front?
I wouldn’t make my html less semantic or clutter it with extra code to save a few milliseconds, but I would change
ul#nav li a
as a matter of practice, since the second is faster and requires no change to the html.
Are you going to notice the difference on most of the sites you develop? Again not likely, but still why wouldn’t you choose to be more efficient where you can?
I wouldn’t take this information and start recoding live sites to make them more efficient, but why not take a few minutes to learn which selector patterns perform better and use the more efficient patterns when you have the choice to use several.
Testing Your Selectors
Steve Souders created a page where you can test different selectors to compare their efficiency. I’ve played with it a little ad the results agree with what I’ve posted above.
I don’t know how accurate the test results are, but it’s worth playing around to get a feel for how quickly some selectors are in comparison to others.
Jon Sykes ran some tests of his own a few years ago mainly to look at the effect of descendent selectors on performance.
His conclusion at the end of the series:
be aware that descender and child selectors can affect performance, but don’t worry about them so much as to not use them.
After seeing the tests above Steve Souders ran his own test coming to the conclusion that the gains from optimizing selectors are probably not worth the cost for most sites.
In a later post he received some feedback about web pages where inefficient selectors did make a noticeable difference and ultimately recommends optimizing the key selector of css selectors.
There’s definitely a performance hit in using some selector patterns over others, but how significant is that performance hit? The answer will depend on the specific site and selectors.
For most sites it probably won’t make much of a difference. You shouldn’t be concerned that the selectors you used developing your last site now need to be revisited and optimized.
However you may want to consider selector efficiency when developing your next site. At the very least it makes sense to understand which patterns are more and less efficient.
Every little bit helps so why not be more efficient where you can be and if you happen to be working on that large trafficked site those little bits can add up to significant savings.
Have you spent any time optimizing your css selectors? Have you noticed any difference in page load times and was it worth the effort?