Selector performance
Learn selector performance and optimization.
Selectors are read right to left
When the browser applies a CSS declaration, it reads the selector right to left. The rightmost piece is called the key selector and is what really drives performance.
For example, in #nav li a the browser first finds every <a> element, then checks whether each has an <li> ancestor, and finally filters to those inside #nav. With hundreds of links this is expensive.
Class-based selectors are efficient
An efficient selector is one where the browser does the least matching work. Class selectors (.menu-item) are ideal for this: they find every match in one pass.
Naming methods like BEM use a single class instead of deep descendants. Writing .card__title is faster than writing .card .card-body .card-title. Each class is its own key selector.
Exercise Convert the inefficient selector to a class
Complete the CSS below. Replace the deep descendant selector #main .content ul.list li.item a.link with a single class selector .nav-link. Inside it add color: #1d4ed8 and text-decoration: none.
Show example solution
/* old deep selector */
#main .content ul.list li.item a.link {
color: #1d4ed8;
text-decoration: none;
}
/* new efficient selector */
.nav-link {
color: #1d4ed8;
text-decoration: none;
}
Test yourself
-
Which selector is the most efficient?
/* all three match the menu item */ #main ul li.menu-item { ... } .menu-item { ... } ul li a { ... }- #main ul li.menu-item
- .menu-item
- ul li a
- #main ul li
Show answer
.menu-item — Correct. .menu-item matches the class directly; it is shallow and the key selector is narrow.
-
Replace the deep selector with a class selector
/* instead of #main ul li.menu */ ____ { padding: 0.5rem; }Show answer
/* instead of #main ul li.menu */ .menu-item { padding: 0.5rem; } -
Match each selector type to its cost
- #id
- Fastest, single element
- .class
- Fast, group match
- tag
- Medium, all tags
- div p
- Slow, descendant scan