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.
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.
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 #tocis 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 .chapterto.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-imageon 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.
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.

Help


