[css3-animations] Splitting up concepts of "animations"

Currently, animations start as soon as the selector containing them
matches some element.  In general, the intent here is that the
selectors capture different "states" the element can be in.  Some
animations are conceptually attached to the element entering a state,
while others are conceptually attached to an element being *in* a
state.  For example, an author may have a tooltip spiral into view
when it is first shown (running an animation when it "enters" the
visible state), and then throb as long as it is shown (running an
animation "during" the visible state).

The current model, where the two situations are distinguished by their
animation-play-count (a number indicates an "enter" animation, the
'infinite' token indicates a "during" animation), is sufficient to
handle these two cases.  However, there is a third case that will
likely be common, where an author wants to run an animation when an
element is *leaving* some state.  For example, taking the tooltip
example given earlier, the author may want to spiral the tooltip out
of view when it is no longer shown.  This use-case cannot be addressed
by the use of animation-play-count.  Naively adding some mechanism for
an animation to run when a selector stops matching rather than when it
stops also isn't ideal, as it would potentially allow an infinite
animation to be run when an element stops matching a selector, with no
way to stop it.

I propose to address this use-case and solve this problem by
explicitly separating the concepts of an animation run when an element
enters a state, leaves a state, or is in a state.  Rather than a
single "animation" shorthand property, and an associated set of
"animation-*" subproperties, I propose having three shorthand
properties, "play-in", "play-out", and "play-during".  (Names are in
the air, other suggestions are "play-enter", "play-exit", and
"play-while".)  Three nearly-identical sets of associated
subproperties would also be defined.

An animation specified in a play-in property runs whenever an element
first gains the specified animation (this is identical to the current
rules for when to run an animation).

An animation specified in a play-out property runs when an element
*loses* the specified animation.  (This is an inverse of the current
rules for when to run an animation, and should work similarly if you
stop matching a selector that gives an animation but still match some
other selector that gives the same animation.  That is, it shouldn't
run.)

"play-in-play-count" and "play-out-play-count" don't allow the
'infinite' token.  They only accept numerical values, or the other
allowed keywords.

An animation specified in a play-during property runs as long as the
element has the specified animation (same as the current rules for
when to run an animation).  play-during animations have an infinite
play-count by default; the play-during shorthand does *not* accept a
play-count value, and there is no play-during-play-count property.


Issues yet to be resolved:

1. How do we deal with animations given in different play-* properties
that try to manipulate the same properties?  We can't rely on the
standard "last animation wins" approach, as the animations occur in
separate lists.  I propose that "play-during" animations win over
"play-in" animations, and "play-out" animations win over
"play-during".


To illustrate this syntax, let's look at the tooltip example given
earlier in this email.  It would be specified as:

.tooltip {
  opacity: 0;
  display: none;
  transition: opacity 1s, display step-start 1s;
}

.tooltip.visible {
  opacity: 1;
  display: block;
  transition: opacity 1s, display step-end 1s; /* This is required to
make sure that you set display at the right time. */
  play-in: spiral 1s;
  play-during: throb 5s 1s; /* A slow throb, delayed by 1s to let the
transition and play-in animation finish first. */
  play-out: spiral reversed 1s; /* This uses the "reversed keyframe"
concept expressed in a separate email. */
}

Now, when you set .visible on the .tooltip element, you will play the
spiral animation over 1s, then continuously run the throb animation as
long as it's visible, then run spiral in reverse when you remove the
.visible class.

~TJ

Received on Tuesday, 6 April 2010 00:13:50 UTC