[css3-transitions] suppression of transition starting, inheritance

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