[csswg-drafts] [web-animations-2][css-animations-2] What to do with keyframe offsets outside of animations. (#7825)

flackr has just created a new issue for https://github.com/w3c/csswg-drafts:

== [web-animations-2][css-animations-2] What to do with keyframe offsets outside of animations. ==
In https://github.com/w3c/csswg-drafts/issues/7044 we https://github.com/w3c/csswg-drafts/issues/7044#issuecomment-1175722383 to add phase linked offsets to the animations APIs. This allows tying both the animation start/end and keyframes to particular parts of the overall timeline time. However, this also allows accidentally specifying keyframe offsets which are before 0% or after 100% of the animation, e.g.

```css
@keyframes fade-in-animation {
  enter 0% { opacity: 0; }
  enter 100% { opacity: 1; }
}
.elem {
  animation: fade-in-animation;
  animation-timeline: view-timeline;
  animation-delay: enter 50% enter 100%;
}
```

The above is obviously a mistake, though you could imagine cases if lengths or calculations are allowed (e.g. #7575) we could end up in this situation dynamically in more legitimate incidental cases, e.g.

```css
@keyframes fade-in-animation {
  /* When 20% of the enter phase is
   * less than 50px this will be < 0% progress. */
  enter 20% { opacity: 0; }
  enter 100% { opacity: 1; }
}
.elem {
  animation: fade-in-animation;
  animation-timeline: view-timeline;
  animation-delay: enter 50px enter 100%;
}
```

I can think of 4 options for how to handle this:

1. Treat keyframes resolving outside of 0 - 100% as an error. This is what [is specified in css-animations-1](https://www.w3.org/TR/css-animations-1/#keyframes):
   > Values less than 0% or higher than 100% are invalid and cause their <keyframe-block> to be ignored.

   and [is also specified by web-animations-1](https://www.w3.org/TR/web-animations-1/#processing-a-keyframes-argument):
   > Specifying an offset outside the range [0.0, 1.0] will cause a TypeError to be thrown.

   However, if we allow length calculated offsets it will not be possible at animation construction time to know whether a future size of scrolling box will result in an invalid keyframe offset. Canceling the animation seems dangerous as this state would often be ephemeral. Naively, we could simply skip the animation when this happens (the same as if the timeline was currently inactive). This could result in sudden flips in visible styles when box sizes pass this threshold.

2. Allow animation offsets outside of 0 - 100% and interpolate from their offset. These would not change the timing of the animation but at 0% animation progress we would interpolate between the keyframes. E.g. if a -50% keyframe specified `opacity: 0` and a 50% keyframe specified `opacity: 1` then at 0% progress when the animation starts it would produce `opacity: 0.5`. This would result in a continuous effect as the box size changed and probably matches developer expectations.

   To do this we would have to change the implicit from and to keyframes to only exist when we don't have a computed keyframe `<= 0%` or `>= 100%`. Relevant [text of css-animations-1](https://www.w3.org/TR/css-animations-1/#keyframes) is:
   > If a 0% or from keyframe is not specified, then the user agent constructs a 0% keyframe using the computed values of the properties being animated. If a 100% or to keyframe is not specified, then the user agent constructs a 100% keyframe using the computed values of the properties being animated.

   The relevant [text of web-animations-1](https://www.w3.org/TR/web-animations-1/#the-effect-value-of-a-keyframe-animation-effect):

   > `9.` If there is no [keyframe](https://www.w3.org/TR/web-animations-1/#keyframe) in property-specific keyframes with a [computed keyframe offset](https://www.w3.org/TR/web-animations-1/#computed-keyframe-offset) of 0, create a new keyframe with a computed keyframe offset of 0, a property value set to the [neutral value for composition](https://www.w3.org/TR/web-animations-1/#neutral-value-for-composition), and a [composite operation](https://www.w3.org/TR/web-animations-1/#composite-operation) of [add](https://www.w3.org/TR/web-animations-1/#composite-operation-add), and prepend it to the beginning of property-specific keyframes.
   > `10.` Similarly, if there is no [keyframe](https://www.w3.org/TR/web-animations-1/#keyframe) in property-specific keyframes with a [computed keyframe offset](https://www.w3.org/TR/web-animations-1/#computed-keyframe-offset) of 1, create a new keyframe with a computed keyframe offset of 1, a property value set to the [neutral value for composition](https://www.w3.org/TR/web-animations-1/#neutral-value-for-composition), and a [composite operation](https://www.w3.org/TR/web-animations-1/#composite-operation) of [add](https://www.w3.org/TR/web-animations-1/#composite-operation-add), and append it to the end of property-specific keyframes.

   The challenge is that when this condition occurs is dynamic so these 0% / 100% keyframes may be needed some of the time and not other times.

3. Clamp calculated animation offsets outside of 0 - 100% to 0 - 100%. This is similar to the above except that when an animation offset would resolve outside of 0 - 100% it is computed to 0 or 100%. E.g. if a -50% keyframe specified `opacity: 0` and a 50% keyframe specified `opacity: 1` then at 0% progress when the animation starts it would produce `opacity: 0` as the -50% keyframe would have been clamped to 0%. This would result in a continuous effect as box sizes change, but the compressing of effects likely doesn't match developer expectations.

4. Skip keyframes with offsets outside of 0 - 100%. When a keyframe offset computes outside of 0 - 100%, exclude that keyframe. E.g. if a -50% keyframe specified `opacity: 0` and a 50% keyframe specified `opacity: 1` then it would be as if only the 50% keyframe were specified, so at 0% progress when the animation starts it would produce the underlying opacity through the implicit keyframe constructed by [css-animations-1](https://www.w3.org/TR/css-animations-1/#keyframes) or [web-animations-1](https://www.w3.org/TR/web-animations-1/#the-effect-value-of-a-keyframe-animation-effect).

My proposal would be to go with option 2 as I believe it leads to the least developer surprise and allows the effect to be continuous even as block sizes change. This is also consistent with the logic from #7432 where we resolved to not clamp the view timeline progress range to the actually scrollable range.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/7825 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 4 October 2022 15:14:31 UTC