Movatterモバイル変換


[0]ホーム

URL:


Skip to contentSkip to sidebar
/Blog
Try GitHub CopilotSee what's new

Optimizing large selector sets

CSS selectors are to frontend development as SQL statements are to the backend. Aside from their origin in CSS, we use them all over our JavaScript. Importantly, selectors are declarative,…

|
|3 minutes
  • Share:

CSS selectors are to frontend development as SQL statements are to the backend. Aside from their origin in CSS, we use them all over our JavaScript. Importantly, selectors are declarative, which makes them prime candidates for optimizations.

Browsers have a number of ways of dealing with parsing, processing, and matching large numbers of CSS selectors. Modern web apps are now using thousands of selectors in their stylesheets. In order to calculate the styles of a single element, a huge number of CSS rules need to be considered. Browsers don’t just iterate over every selector and test it. That would be way too slow.

Most browsers implement some kind of grouping data structure to sort out obvious rules that would not match. In WebKit, it’s called aRuleSet.

SelectorSet

SelectorSet is a JavaScript implementation of group technique browsers are already using. If you have a set of selectors known upfront, it makes matching and querying elements against that set of selectors much more efficient.

Selectors added to the set are quickly analyzed and indexed under a key. This key is derived from a significant part of the right most side of the selector. If the selector targets an id, the id name is used as the key. If there’s a class, the class name is used and so forth. The selector is then put into a map indexed by this key. Looking up the key is constant time.

When it’s time to match the element against the group, the element’s properties are examined for possible keys. These keys are then looked up in the mapping which returns a smaller set of selectors which then perform a full matches test against the element.

Speeding up document delegated events

jQuery’s original$.fn.live function (and its modern form,$.fn.on) are probably the most well known delegation APIs. The main advantage of using the delegated event handler over a directly bound one is that new elements added afterDOMContentLoaded will trigger the handler. A technique like this is essential when using a pattern such aspjax, where the entire page never fully reloads.

Extensive usage ofdocument delegated event handlers is considered controversial. This includes applications with a large number of$(‘.foo’).live(‘click’) or$(document).on(‘click’, ‘.foo’) registrations. The common performance argument is that the selector has to be matched against entire ancestor chain of the event target. On an application with large and deeply nested DOM, like github.com, this could be as deep as 15 elements. However, this is likely not the most significant factor. It is when the number of delegated selectors themselves is large. GitHub has 100+ andBasecamp has 300+ document delegated events.

Using the selector set technique described above, installingthis jQuery patch could massively speed up your apps event dispatch. Here’s a fun littlejsPerf test using real GitHub selectors and markup to demonstrate how much faster the patched jQuery is.

Conclusion

Both of these libraries should be unnecessary and hopefully obsoleted by browsers someday. Browsers already implement techniques like this to process CSS styles efficiently. It’s still unfortunate we have no native implementation of declarative event handlers, even though people have been doing this since2006.

References

Written by

Related posts

News & insights

The future of AI-powered software optimization (and how it can help your team)

We envision the future of AI-enabled tooling to look like near-effortless engineering for sustainability. We call it Continuous Efficiency.

Illustration of a chemistry lab setup with interconnected glassware and tubing. Beakers, flasks, test tubes, and a large central reaction vessel contain glowing green and blue liquids. A pressure gauge, condenser coil, funnels, and heating plates appear along a blue tiled lab wall, with fluids flowing through tubes between the containers.
News & insights

Let’s talk about GitHub Actions

A look at how we rebuilt GitHub Actions’ core architecture and shipped long-requested upgrades to improve performance, workflow flexibility, reliability, and everyday developer experience.

Company news

GitHub Availability Report: November 2025

In November, we experienced three incidents that resulted in degraded performance across GitHub services.

Explore more from GitHub

Docs

Docs

Everything you need to master GitHub, all in one place.

Go to Docs
GitHub

GitHub

Build what’s next on GitHub, the place for anyone from anywhere to build anything.

Start building
Customer stories

Customer stories

Meet the companies and engineering teams that build with GitHub.

Learn more
The GitHub Podcast

The GitHub Podcast

Catch up on the GitHub podcast, a show dedicated to the topics, trends, stories and culture in and around the open source developer community on GitHub.

Listen now

We do newsletters, too

Discover tips, technical guides, and best practices in our biweekly newsletter just for devs.


[8]ページ先頭

©2009-2025 Movatter.jp