- From: L. David Baron <dbaron@dbaron.org>
- Date: Thu, 11 Jun 2009 09:48:44 -0400
- To: www-style@w3.org
http://dev.w3.org/csswg/css3-transitions/ doesn't currently have a processing model that explains exactly what makes a transition start. I think one rule for what should start a transition is that any change to the computed value of a CSS property that is not part of an animation (where part of an animation includes changes caused by a transition or changes caused by other animation technology, including both the first and last steps of such animation). I think the spec ought to say something like that. However, even that description doesn't define how this interacts with inheritance. To explain what I mean by this, I'd like to walk through two ways of processing the dynamic change in this example when the outermost div (a) is hovered (changing its color from blue to purple): <style type="text/css"> #a { color: blue; } #a:hover { color: fuchsia; } #b { transition: 3s color; } #c { transition: 10s color; } </style> <div id="a"> <div id="b"> Text in B. <div id="c"> Text in C. </div> </div> </div> In the first method of processing, the implementation takes the following steps: 1) When div#a enters the :hover state, it computes the style change for the entire document tree. 2) It compares the old and new styles resulting from that change, and determines that the style changes on both div#b and div#c require starting transitions. 3) The color of "Text in B" then transitions over 3 seconds, while the color of "Text in C" transitions over 10 seconds. This processing model has a serious deficiency: if we swap the times so that the inner element has the shorter time, then that inner element transitions twice: after completing its transition, it picks up inheriting the end part of the transition of its ancestor. If we try to further change the model to prevent that problem, we're likely to end up with two additional problems: a) a complex model for suppressing inheritance of transitions (I expect it would be hard to define this, especially in the presence of multiple transitions occurring that happen at different times) b) a discontinuity between transition-duration: 1ms and transition-duration: 0, because transition-duration: 0 (combined with transition-delay: 0) is the default that we use to indicate that no transitions need to happen. (And I don't see how to fix this one other than by changing the the initial value of transition-property to none, and having separate transition-duration-inherited and transition-duration-not-inherited for properties that inherit by default or don't (which follow the same inheritance as the properties they apply to), so I don't think this is a realistic approach.) In the second method of processing, the implementation instead does the following: 1) When div#a enters the :hover state, it starts computing the style change for the document tree. The order it does this in doesn't strictly matter, but because of inheritance it has to happen ancestors-before-descendants. 2) When it finishes computing the style change for div#b but before it starts computing the style change for any of its descendants, it compares the old and new styles resulting from the style change on div#b and recognizes that it needs to start a transition. 3) It immediately resets the computed style for div#b back to the value before the transition, before computing the style change for any of the descendants of div#b. (Note that I've chosen the wording very carefully here. In most cases, the style at the start of the transition is the same as it was before the transition began, but this is not always the case -- for example, with negative transition-delay. In this case, we actually want to use the value before the transition in this step so that we don't trigger the start of transitions on descendant elements.) 4) While computing the style changes for descendants of div#b, styles that haven't changed as a result of the fixup in (3) don't trigger the start of additional transitions. 5) After the entire document tree has had style recomputed, immediately initiate the transitions that started by transitioning to the style at the start of the transition. (As I mentioned in (3), this style is only going to be different in the case of negative transition-delay.) These style changes should be considered as caused by an animation, and thus don't trigger the start of new transitions. This processing model has the disadvantage that a long-duration transition can be hidden by a shorter-duration transition on an ancestor. So, again, there is a discontinuity, but this time between the ancestor having transition-duration: 0 and transition-duration: 1ms. I wrote a test (basically the above example, plus some borders to make things more visible) to see what's happening in existing implementations: http://lists.w3.org/Archives/Public/www-archive/2009Jun/att-0073/transition.html and it looks like my somewhat-out-of-date version of WebKit does neither of these: when transition in to :hover, it starts the inner transition when the outer one completes, but when transitioning out of hover, it gives the result expected with the first model. -David -- L. David Baron http://dbaron.org/ Mozilla Corporation http://www.mozilla.com/
Received on Thursday, 11 June 2009 13:49:20 UTC