[css3-transitions] Adding keyframes to transitions

While I don't personally believe that Transitions and Animations will
benefit from being fully merged, I do think that we need the ability
to manipulate more than just the property that is changing during a
transition.  Simon Fraser put together an excellent example of a
sliding box in a container; when you hovered the container, the box
would slide from left to right (a transition on the "left" property),
and would also wobble up and down (an animation manipulating the "top"
property).

Right now, you can't hook these two actions together.  You have to
specify something like this:

@keyframes bounce {
  from { top: 0; }
  25% { top: -20px; }
  50% { top: 0; }
  75% { top: 20px; }
  to { top: 0; }
}

.slider > .box {
  left: 0;
  transition: left 1s;
}

.slider:hover > .box {
  left: 400px;
  animation: bounce 1s;
}

This has several problems:

1. Even though, conceptually, you're wanting to say "when left
changes, animate it and also bounce", the syntax as currently drafted
doesn't indicate that.  Instead, you have a "left" transition, and
then separately, a bounce animation that happens to occur at the same
time and have the same duration.

2. When you stop hovering, the "left" will still transition, but the
bounce animation won't run again.  To fix that you have to specify an
animation on ".slider:not(:hover) > .box" as well, which is
unintuitive and extraneous.  This still doesn't work right, though, as
the box will now bounce on page load (since the selector matches).
You have to use javascript to get around this (to be precise, you have
to set a class on the slider when you hover it for the first time, and
qualify the reverse animation with that class).

3. This doesn't address any other conditions that could change the
"left" value of .box.  To do that, you have to set up additional
animations, and reverse animations, for each separate one.  This
creates a combinatorial explosion (if you have 3 states that could
change "left", you need to set up 6 animations, etc.)

4. Animations don't run again if you change from one state specifying
the animation to another state specifying the same animation.  To get
it to run in reverse, you have to define a *second* keyframe that is
exactly identical except with a different name, and use that for the
reverse transition.  If you have multiple states (see #3), you have to
replicate the keyframe with a unique name for every possible
transition.

All of these are caused by the fact that you're trying to animate
"top" when "left" changes, but the syntax doesn't allow you to
actually *say* that.  I propose a slight change to the syntax of
transition-property to express this more properly.  In addition to
taking the name of a property, transition-property also takes a
"play(<property name>, <keyframe name>)" function.  This specifies a
keyframe to run when the specified property changes.  The example from
the beginning of this email would then be:

@keyframes bounce {
  from { top: 0; }
  25% { top: -20px; }
  50% { top: 0; }
  75% { top: 20px; }
  to { top: 0; }
}

.slider > .box {
  left: 0;
  transition: left 1s, play(left, bounce) 1s;
}

.slider:hover > .box {
  left: 400px;
}

This now expresses the intention much more clearly (I am running the
bounce animation when the left property changes), and thus makes the
entire thing *actually work*.  I don't need to jump through any hoops
to run the animation when I stop hovering, and if any additional
states could change the "left" value, the animation will run for them
as well.

Issues that aren't yet resolved (but I think are fairly easy):

1. What if my bounce animation happened to also manipulate "left"?  I
believe we can rely on the standard rule for animations, where the
last specified animation wins whenever there is a conflict in what a
value should be.  A plain transition can then be thought of as an
auto-created trivial keyframe manipulating the given property.

2. I believe that true animations automatically override transitions.
This should apply equally to both plain transitions and keyframe
transitions.

I think this is the minimal syntax addition that expresses the display
semantics we want.  I also think this fully addresses the use-case I
identified, that of manipulating multiple properties whenever a given
property's value changes.

~TJ

Received on Monday, 5 April 2010 23:35:28 UTC