CSS Selectors: Should You Optimize Them To Perform Better?

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.

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.

Man reading a book while standing neck deep in water

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.

1
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?

Sustainability graphic on Performance.gov, earth with 2 arrows circling

Selector Efficiency

Below is the order of efficiency for selectors. IDs are the most efficient and pseudo classes and pseudo elements are the least efficient.

  1. id (#myid)
  2. class (.myclass)
  3. tag (div, h1, p)
  4. adjacent sibling (h1 + p)
  5. child (ul > li)
  6. descendent (li a)
  7. universal (*)
  8. attribute (a[rel=”external”])
  9. 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.

1
div #myid

will be more efficient than

1
#myid div

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

1
2
#myid
.myclass

are more efficient than

1
2
p#myid
p.myclass

Mozilla Firefox logo superimposed over image of a space nebula

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.

Line drawing of a robot with a question mark in a thought bubble

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

1
#myid

is more efficient than

1
p#myid

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

1
ul#nav li a

to

1
#nav 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.

Boxes with the word test across them

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.

Presentation slide talking about the css selector api

Summary

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?

Download a free sample from my book, Design Fundamentals.

13 comments

  1. Very nice analysis of CSS selector. I’ve recently read about this topic, and was concerned because I often use somewhat complicated CSS selectors to keep HTML semantic. For example, I often use a body class combined with one or more child selectors, to select specific parts of specific pages with minimal use of classes and ids in markup. I think I’ll keep using selectors like this, favoring clean markup over saving a few milliseconds in CSS rendering. But it’s good to understand the trade-offs and what is necessary to make CSS render faster.

    • Thanks kayan. The biggest takeaway from all this performance talk is that unless your site is large and gets a lot of traffic you probably don’t need to be overly concerned.

      At the same time if you can make that “key selector” more efficient you might as well.

      I’m with you on favoring the clean markup. At some point you’d think adding extra markup everywhere could also lead to a few milliseconds of slower load time.

      One of the things I want to look into more is objective css, which makes good use of classes for reusable styles. It adds some extra code, but naturally being able to use classes as selectors would help with selector performance.

    • I assume Google is pointing to everything that could potentially help, though some things will have more significant time savings than other things.

      CSS selectors seem to have limited impact with the exception of larger more heavily trafficked sites.

      At the same time why not optimize where you can. I wouldn’t necessarily spend hours upon hours optimizing css selectors, but I would learn the basic ideas in order to write faster selectors as general practice.

    • It would depend on how much I suppose. I agree that it wouldn’t make sense to start adding ids or classes to every element just to make your selectors faster.

      There’s probably a good balance though between adding ids for selector performance and not adding them so there’s less html.

  2. Great article! love it!

    The first time I ran into the topic of CSS selector performance was while reading the awesome “Even Faster Websites” book by Steve Souders, who you mention above. Certainly, this article builds above that.

    Thanks for the great materials!

  3. Nice, thorough article Antonin, thanks. I’ve recently been reading a little about making key selectors more efficient whilst still taking advantage of the power of the cascade, and this nails some of the central issues nicely for me. I think I’m inclined to also follow the route of clean, semantic html and just be more mindful of those extraneous child selectors that can sometimes creep into my css.

    • Thanks Marc. I’m leaning toward the clean and semantic html as you can tell, though I will start paying more attention to selectors with the knowledge of how efficient one is over another.

Leave a Reply

Your email address will not be published.

css.php