- From: Boris Zbarsky <bzbarsky@mit.edu>
- Date: Mon, 21 Aug 2006 10:51:19 -0500
- To: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
- CC: www-style@w3.org, Kelly <lightsolphoenix@gmail.com>
Giuseppe Bilotta wrote: > IANAI (I Am Not An Implementor), but I don't really see how this is > any different from having to know the entire content of the element > before rendering it. The main difference is how much needs to be recomputed and how often. > And by judging from what I see in Opera or Mozilla, dynamic/progressive restyling is not really a problem This is only true in Mozilla (which is the implementation I'm familiar with) because it's buggy. We haven't even figured our a reasonably efficient way to implement dynamic changes to :empty yet, for example. As a result, such dynamic changes are broken. > and *after* all > the juggling is done I add a <style>...</style> element to my document > with all the CSS I'm interested in ... and *poof* the page gets > rendered correctly. Again, I can only speak for Mozilla. What Gecko does in this case is to simply reresolve style for everything in the tree, starting with the root element and going down. This is very expensive, but in this case we make the (correct, imo) assumption that tossing an entire stylesheet into the document is a very rare operation, so doing it slowly is acceptable. For a document of any appreciable size (say for example the unzipped version of http://downloads.mysql.com/docs/refman-5.1-en.html.zip) this stle recomputation takes on the order of tens of seconds. > Even without considering these extreme cases, a lot of complex pages > with no JS code require some rendering box shuffling and restyling > *while loading*, and both Opera and SeaMonkey seem to handle them > pretty well. The only restyling that Gecko handles correctly at the moment is: 1) Styles the only depend on the element's attributes/state 2) The '>' combinator There are, as I said, known bugs with :empty; the behavior of '+' and '~' is ok for changes to state, but NOT for insertions into the document or removals from it. Luckily, during the load of a page there are no such insertions or removals (because the '+' and '~' combinators only affect style of things after the node being inserted or removed, and during pageload nodes are always added at the end). So in Gecko those combinators sort of work during pageload, but not during JS manipulation of the page. Going into a little more detail, the way that Gecko implements dynamic changes at the moment is the following: when a node's state changes, we determine the set of nodes whose style may have changed as a result, and recompute their style. For the '~' combinator, for example, this is the the set of following siblings of the node (and all their descendants, but that's implied anyway due to CSS inheritance). This particular condition is very easy to express: "If the state of a node has changed such that it ceases or starts matching the sequence of simple selectors on the left of a '~' combinator, style needs to be recomputed on all following siblings of the node." Checking whether this condition applies is very fast -- simply match the node against the left sides of all '~' combinators. Recomputing the style itself might be a little slow, however, but we've accepted that as a tradeoff, especially because during pageload (which is the #1 most common dynamic restyling case) there are no following siblings around. With regard to insertions of DOM nodes, the condition for '~' is: "If a node is inserted and either it, or any of its previous siblings matches the sequence of simple selectors on the left of a '~' combinator, style needs to be recomputed on all following siblings of the node." Note that checking whether this condition applies is much slower due to the need to examine all previous siblings, unless one simply assumes that style on following siblings should be recomputed all the time. Either approach makes incremental layout at best O(N^2) in the number of increments, leading to serious performance degradation of pageload. This is why this case is not handled correctly by Gecko -- we haven't found a way to do it right without regressing pageload performance yet. Now consider parent/predecessor selectors in all their forms (:matches, parent combinators, etc). Let's take the parent combinator as a simple to analyze example. The condition for correctness on insertion in this case is: "If a node is inserted, and any node anywhere in the document matches the sequence of simple selectors on the left of a parent combinator, style needs to be recomputed on all nodes in the document." No comment on pageload performance. > So please help me get something right: Opera and SeaMonkey already > handle similar situations My point is that Gecko doesn't handle them. I can't speak for Opera. > Plus, as Allan Sandfeld Jensen mentions: I'd love to see Allan's implementation; it may give me some ideas on how to do this in Gecko. I'd also like to do some performance testing on it as compared to Gecko, of course. ;) > Even worse, I don't understand /who/ is objecting Last I checked, people involved in Gecko (myself, say) and Webkit [Safari] (David Hyatt, say) were having concerns about being able to implement this in a performant way. -Boris
Received on Monday, 21 August 2006 15:51:44 UTC