-
Notifications
You must be signed in to change notification settings - Fork 746
Description
CSS Animations Level 2 describes the handling of animation-play-state
as follows:
If at any time, including when the animation is first generated, the resolved value of animation-play-state corresponding to an animation is newly running, the implementation must run the procedure to play an animation for the given animation with the auto-rewind flag set to false.
That is, whether or not a new CSS animation is created or updated, the play procedure is run with the auto-rewind flag set to false.
However, if we follow that procedure through for a new CSS animation, it won't work:
...
- Perform the steps corresponding to the first matching condition from the following, if any:
- If animation’s effective playback rate > 0, the auto-rewind flag is true and either animation’s:
- current time is unresolved, or
- current time < zero, or
- current time ≥ associated effect end,
- Set seek time to zero.
At this point auto-rewind is false so we skip this step.
- If animation’s effective playback rate < 0, the auto-rewind flag is true and either animation’s:
- current time is unresolved, or
- current time ≤ zero, or
- current time > associated effect end,
- If associated effect end is positive infinity,
- throw an "InvalidStateError" DOMException and abort these steps.
- Otherwise,
- Set seek time to animation’s associated effect end.
- If animation’s effective playback rate = 0 and animation’s current time is unresolved,
- Set seek time to zero.
In fact, none of the steps above match so seek time is still unresolved.
- If seek time is resolved,
- If has finite timeline is true,
- Set animation’s start time to seek time.
- Let animation’s hold time be unresolved.
- Apply any pending playback rate on animation.
- Otherwise,
- Set animation’s hold time to seek time.
Again, seek time is unresolved so we don't set the hold time or start time.
- If animation’s hold time is resolved, let its start time be unresolved.
Hold time is unresolved so we don't touch the start time.
...
- If the following four conditions are all satisfied:
- animation’s hold time is unresolved, and
- seek time is unresolved, and
- aborted pause is false, and
- animation does not have a pending playback rate,
abort this procedure.
Since all these conditions hold, we end up aborting the procedure.
Why do browsers work at all then?
For Blink, it looks like it uses a different code path for a new animation vs updating an existing animation
- For a new animation it uses the
play
method which does not set auto-rewind to false. - For an existing animation it uses the
Unpause
method which does set auto-rewind to false.
Hence it doesn't hit this issue. I believe @BorisChiou looked into WebKit and found something similar.
Gecko doesn't quite follow the spec correctly for step 5 above and so far hasn't hit this issue but in trying to fix step 5 we ran into it.
Possible fixes
I think there are at least two possible approaches to fixing this:
- Make the procedure to play an animation ignore the auto-rewind flag if the current time is unresolved
- Make CSS Animations level 2 distinguish between playing a new animation vs unpausing an existing animation
I think the first option is cleaner and more intuitive -- if you try to play an animation without a current time, it should play from the start, regardless of whether or not you set auto-rewind to false since it's not rewinding.
I think that would be equivalent to changing the following text from:
If animation’s effective playback rate = 0 and animation’s current time is unresolved,
- Set seek time to zero.
to just:
If animation’s current time is unresolved,
- Set seek time to zero.
I wonder what else that might break, though?