What happened to the “Use efficient CSS selectors”

2020-02-28 06:58发布

问题:

There was a recommendation by Google PageSpeed that asked web developers to Use efficient CSS selectors:

Avoiding inefficient key selectors that match large numbers of elements can speed up page rendering.

Details

As the browser parses HTML, it constructs an internal document tree representing all the elements to be displayed. It then matches elements to styles specified in various stylesheets, according to the standard CSS cascade, inheritance, and ordering rules. In Mozilla's implementation (and probably others as well), for each element, the CSS engine searches through style rules to find a match. The engine evaluates each rule from right to left, starting from the rightmost selector (called the "key") and moving through each selector until it finds a match or discards the rule. (The "selector" is the document element to which the rule should apply.)

According to this system, the fewer rules the engine has to evaluate the better. [...]. After that, for pages that contain large numbers of elements and/or large numbers of CSS rules, optimizing the definitions of the rules themselves can enhance performance as well. The key to optimizing rules lies in defining rules that are as specific as possible and that avoid unnecessary redundancy, to allow the style engine to quickly find matches without spending time evaluating rules that don't apply.

This recommendation has been removed from current Page Speed Insights rules. Now I am wondering why this rule was removed. Did browsers get efficient at matching CSS rules in the meantime? And is this recommendation valid anymore?

回答1:

In Feb 2011, Webkit core developer Antti Koivisto made several improvements to CSS selector performance in Webkit.

Antti Koivisto taught the CSS Style Selector to skip over sibling selectors and faster sorting, which bring some minor improvements, after which he landed two more awesome patches: one which enables ancestor identifier filtering for tree building, halving the remaining time in style matching over a typical page load, and a fast path for simple selectors that speed up matching up another 50% on some websites.

CSS Selector Performance has changed! (For the better) by Nicole Sullivan runs through these improvements in greater detail. In summary -

According to Antti, direct and indirect adjacent combinators can still be slow, however, ancestor filters and rule hashes can lower the impact as those selectors will only rarely be matched. He also says that there is still a lot of room for webkit to optimize pseudo classes and elements, but regardless they are much faster than trying to do the same thing with JavaScript and DOM manipulations. In fact, though there is still room for improvement, he says:

“Used in moderation pretty much everything will perform just fine from the style matching perspective.”

While browsers are much faster at matching CSS selectors, it's worth reiterating that CSS selectors should still be optimised (eg. kept as 'flat' as possible) to reduce file sizes and avoid specificity issues.



回答2:

Here's a thorough article (which is dated early 2014)

I am quoting Benjamin Poulain, a WebKit Engineer who had a lot to say about the CSS selectors performance test:

~10% of the time is spent in the rasterizer. ~21% of the time is spent on the first layout. ~48% of the time is spent in the parser and DOM tree creation ~8% is spent on style resolution ~5% is spent on collecting the style – this is what we should be testing and what should take most of the time. (The remaining time is spread over many many little functions)

And he continues:

“I completely agree it is useless to optimize selectors upfront, but for completely different reasons:

It is practically impossible to predict the final performance impact of a given selector by just examining the selectors. In the engine, selectors are reordered, split, collected and compiled. To know the final performance of a given selectors, you would have to know in which bucket the selector was collected, how it is compiled, and finally what does the DOM tree looks like.

All of that is very different between the various engines, making the whole process even less predictable.

The second argument I have against web developers optimizing selectors is that they will likely make things worse. The amount of misinformation about selectors is larger than correct cross-browser information. The chance of someone doing the right thing is pretty low.

In practice, people discover performance problems with CSS and start removing rules one by one until the problem go away. I think that is the right way to go about this, it is easy and will lead to correct outcome.”

There are approaches, like BEM for example, which models the CSS as flat as possible, to minimize DOM hierarchy dependency and to decouple web components so they could be "moved" across the DOM and work regardless.



回答3:

Maybe because doing CSS for CMSes or frameworks is more common now and it's hard then to avoid using general CSS selectors. This to limit the complexity of the stylesheet.

Also, modern browsers are really fast at rendering CSS. Even with huge stylesheets on IE9, it did not feel like the rendering was slow. (I must admit I tested on a good computer. Maybe there are benchmarks out there).

Anyway, I think you must write very inefficient CSS to slow down Chrome or Firefox...

There's a 2 years old post on performance @ Which CSS selectors or rules can significantly affect front-end layout / rendering performance in the real world?

I like his one-liner conclusion : Anything within the limits of "yeah, this CSS makes sense" is okay.