- 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