Question

WebKit browsers have a built-in optimization technique for style rendering "that results in not even having to match style for about 60% of the elements on your page."

However, that optimization is switched off completely for the entire page if "any sibling selector is encountered anywhere in the stylesheet... This includes the + selector and selectors like :first-child and :last-child."

Does anyone know the complete list of selector types that disable this optimization?

--

More Info

  • The optimization is discussed in Tali Garsiel's study on browser internals: How Browsers Work.

  • Here's the full quote on sibling selectors from Dave Hyatt, who apparently authored the browser code: "There must be no sibling selectors in use at all. WebCore simply throws a global switch when any sibling selector is encountered and disables style sharing for the entire document when they are present. This includes the + selector and selectors like :first-child and :last-child."

  • That quote seems to come from an article Hyatt wrote in 2005. Below he discusses it in more detail (same source as previous):

    "WebCore (in upcoming Safari releases) has a really cool optimization that I came up with to avoid even having to compute the set of declarations that apply to an element. This optimization in practice results in not even having to match style for about 60% of the elements on your page. The idea behind the optimization is to recognize when two elements in a page are going to have the same style through DOM (and other state) inspection and to simply share the front end style information between those two elements whenever possible."

  • This article by Nate Koechley discusses the algorithm in more detail. He sums it up with:

    "In web development there are often 6 different similar ways to do the same thing. What makes a good web developer is continually choosing the best of nearly-indistinguishable paths. These insider tips from Hyatt give us a more complete understanding of the guts of the browsers, and will help us choose the best methods."

  • Hyatt also discussed the optimization in this W3C mailing list archive

  • It also came up briefly in a Stack chat from Ryan Kinal: "Wow. Just wow. I will never use another sibling selector again."

I'm particularly interested in knowing:

  • whether child selectors also turn off the optimization

  • whether Trident/IE uses any similar optimization

  • whether any tests exist that show how big of a difference it makes for rendering performance

Was it helpful?

Solution

I don't have a full list, but this text from mozilla and Servo can be helpful, I think.

WebKit's handling of style updates

Attribute changes

If the element does not already have a style recalc flagged, and if either the attribute is the id attribute or there are selectors that involve the attribute, the element is flagged for a style recalc. There is no attempt to double-check whether those selectors have anything to do with the element and no attempt to handle cases involving '~' and '+' at this stage. There is also a separate hook called when class attributes change that amongst other things unconditionally flags the element as needing a style recalc. Again, no attempt is made to handle '~' and '+'. In none of these cases is there an attempt to optimize away selector matching on descendants.

State changes

There is no unified setup for state changes in WebKit. For each pseudo-class that is handled via boolean states in Gecko, selector matching has a dedicated function the element that it can call to test whether that pseudo-class matches. Changes to that state inside an element are responsible for directly marking that element as needing style recalc. Again, no attempt to optimize away selector matching on descendants or to handle '+' or '~' is made. There are some optimizations here similar to the one Gecko makes for :hover that cover :hover, :active, and something about dragging.

Handling of insertions and deletions

The RenderStyle has flags that indicate whether its kids are affected by various structural pseudo-classes and '+' or '~' combinators. On DOM mutations, the first affected element after the change (in child list order) is marked as needing a style recalc, or the single first child of the parent if it might need a recalc. If more things before the change might need a recalc, then the parent is marked as needing a style recalc, which will recalc all its kids. In all of these cases, when actually recomputing style on an element, a check is made to see whether its kids are affected by '+' or '~'. If so, then if any child is flagged as needing style recalc either the child after it or all children after it (depending on whether '+' or '~' was involved) are also flagged as needing style recalc. There are some bugs here around chains of multiple '+', I think.

The upshot is that in some cases WebKit ends up recomputing style on a lot more elements than Gecko does, as far as I can tell, but in others it ends up recomputing style on many fewer elements. For example, given a selector like ".foo ~ span" and a div that changes class from "foo" to "bar", Gecko will restyle all later siblings of the div, while WebKit will not do any work at all if there are no "span" kids, since it would never have marked the parent as being affected by the '+' in that case. I'm not sure to what extent this affects insertion behavior, where it seems like the two should be more similar. Somehow WebKit seems to do better than Gecko on the HTML5 single-page spec scripts, and I can't figure out why at this point. Perhaps this is simply because its style recomputation seems to be much cheaper than Gecko's to actually run.

The other upshot is that the work involved in individual attribute and state changes is much less than in Gecko, at the cost of more style recomputation. The work involved in DOM insertion/deletion is about the same.

source

OTHER TIPS

I have not seen any such problem with the selectors, until the selector style is with heavy image that takes time to load.

If the css is with inbuilt web colors that should not face any problem with any kind of selectors, according to w3 specification on Selector..

The following rule is similar to the one in the previous example, except that it adds a class selector. Thus, special formatting only occurs when H1 has class="opener":

h1.opener + h2 { margin-top: -5mm }   

SO the rules are standardize but there must be some bug in the webkit browser, which halts on the wait for the particular selector.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top