Jump to content

How to Write Efficient CSS Selectors

  MaryO's Photo
Posted Nov 10 2009 05:59 PM

With this excerpt from Even Faster Web Sites you'll be writing efficient CSS selectors in no time.

The impact of CSS selectors on performance derives from the amount of time it takes the browser to match the selectors against the elements in the document. Developers have some control over how long this matching takes by writing their selectors to be more efficient. The path to efficient selectors starts by understanding how selector matching works.

Rightmost First

Consider the following rule:

#toc > LI { font-weight: bold; }

Most of us, especially those who read left to right, might assume that the browser matches this rule by moving from left to right, and thus, this rule doesn’t seem too expensive. In our minds, we imagine the browser working like this: find the unique toc element and apply this styling to its immediate children who are LI elements. We know that there is only one toc element, and it has only a few LI children, so this CSS selector should be pretty efficient.

In reality, CSS selectors are matched by moving from right to left! With this knowledge, our rule that at first seemed efficient is revealed to be fairly expensive. The browser must iterate over every LI element in the page and determine whether its parent is toc.

Our descendant selector example is even worse:

#toc A { color: #444; }

Instead of just checking for anchor elements inside toc, as would happen if it was read left to right, the browser has to check every anchor in the entire document. And instead of just checking each anchor’s parent, the browser has to climb the document tree looking for an ancestor with the ID toc. If the anchor being evaluated isn’t a descendant of toc, the browser has to walk the tree of ancestors until it reaches the document root.

David Hyatt, Safari and WebKit architect, reveals this information in one of the most-referenced articles on CSS selector performance, “Writing Efficient CSS for use in the Mozilla UI”:

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.

Writing Efficient CSS Selectors

Armed with the insight that selectors are matched right to left, we can take another look at our CSS selectors and tune them to be more efficient. Before we start, it would be nice to have some additional information, such as which CSS selectors are the most expensive, and some patterns for making it easier to fix them. Fortunately, David Hyatt’s article provides guidelines for writing efficient selectors:

Avoid universal rules

In addition to the traditional definition of universal selectors, Hyatt lumps adjacent sibling selectors, child selectors, descendant selectors, and attribute selectors into this category of “universal rules.” He recommends using ID, class, and tag selectors exclusively.

Don’t qualify ID selectors

Because there is only one element in the page with a given ID, there’s no need to add additional qualifiers. For example, DIV #toc is unnecessary and should be simplified to #toc.

Don’t qualify class selectors

Instead of qualifying class selectors for specific tags, extend the class name to be specific to the use case. For example, change LI .chapter to .li-chapter, or better yet, .list-chapter.

Make rules as specific as possible

Don’t be tempted to build long selectors, such as OL LI A. It’s better to create a class, such as .list-anchor, and add it to the appropriate elements.

Avoid descendant selectors

Descendant selectors are typically the most expensive to process. Child selectors are often what’s intended and can be more efficient. It’s even better to follow the next guideline to avoid child selectors as well.

Avoid tag-child selectors

If you have a child selector that is based on a tag, such as #toc > LI > A, use a class associated with each of those tag elements, such as .toc-anchor.

Question all usages of the child selector

This is another reminder to review all places where child selectors are used, and replace them with specific classes when possible.

Rely on inheritance

Learn which properties are inherited, and avoid rules that specify these inherited styles. For example, specify list-style-image on the list element instead of on each list item element. Consult the list of inherited properties to know which properties are inherited for which elements.

It’s interesting to note that David Hyatt’s article was first published in April 2000. I wonder—why is there renewed interest in this topic nine years later? David’s article, as the title states, was addressed to developers working on the Mozilla UI. Perhaps it’s taken this long for web pages to reach a similar level of performance loss with regard to CSS selectors.

Another factor is that today’s Web 2.0 applications have a longer session length—it’s not the load-clear-load Web 1.0 scenario. In this sense, Web 2.0 applications are more similar to the Mozilla UI, and the impact of inefficient CSS selectors may be more pronounced as huge portions of the DOM tree are created and removed, and DHTML code changes class names and style attributes. The findings in the next section support this view that the complexity and dynamic nature of web pages are what have brought focus to this area of performance analysis.

Even Faster Web Sites

Learn more about this topic from Even Faster Web Sites.

Performance is critical to the success of any web site. In this book, Steve Souders, web performance evangelist at Google and former Chief Performance Yahoo!, provides valuable techniques to help you optimize your site's performance. Souders and eight expert contributors provide best practices and pragmatic advice for improving your site's performance in three critical categories: Javascript, in the network, and in the browser.

This book contains six guest chapters contributed by Dion Almaer, Doug Crockford, Ben Galbraith, Tony Gentilcore, Dylan Schiemann, Stoyan Stefanov, Nicole Sullivan, and Nicholas C. Zakas.

See what you'll learn

0 Subscribe

0 Replies