Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[scroll-animations-1] Bring back Scroll Offsets #7575

Closed
bramus opened this issue Aug 4, 2022 · 38 comments
Closed

[scroll-animations-1] Bring back Scroll Offsets #7575

bramus opened this issue Aug 4, 2022 · 38 comments

Comments

@bramus
Copy link
Contributor

bramus commented Aug 4, 2022

One of the things that did not make it into the scroll-animations rewrite is the ability to animate as a scroller scrolls for a fixed distance. This used to be covered by the scroll-offsets.

There are some use-cases, such as this cover page that transforms to a header bar as you scroll over a distance of 90vh.

One could use use a ViewTimeline here, but not on the cover/header element itself because it is sticky and therefore never exits. Instead, one would have to look at the succeeding element.

This, however, is only possible if all of these apply:

  1. There is a succeeding element
  2. That succeeding element is not in view at the start of the animations, so you can watch it enter
  3. The ViewTimeline can be seen by the preceding header

The first 2 conditions might not always be the case, but the author could work around that if they rearrange some things in their markup. The 3rd condition is not possible, since we decided in #7047 to have “timeline search look at preceding siblings and ancestors”.

Therefore I think we should reintroduce the Scroll Offsets.

@ydaniv
Copy link
Contributor

ydaniv commented Aug 7, 2022

Isn't it what we have ScrollTimeline for? Isn't that simply a use-case for that?
Or, if the author prefers using ViewTimeline, then it makes sense they have a revealing element that holds the timeline, and the header is simply the target of the animation. Which should be straightforward using the current API, or did I miss something and it's not?

@ydaniv
Copy link
Contributor

ydaniv commented Aug 7, 2022

Ok, just checked and we did lose that ability on SctollTimeline. We definitely need to have offset and duration defined by <length>s, same as ViewTimeline can define those using phases.
So @bramus I guess this was the intention here?

@bramus
Copy link
Contributor Author

bramus commented Aug 8, 2022

I’ve given this some thought over the weekend, and could think of a few possible scenarios to tackle this:

  1. Bring back the old scroll-offsets as scroll-timeline-offsets

    This seems like a straightforward thing, but is too limiting. For example:

    body {
      scroll-timeline: body-tl block;
      scroll-timeline-offsets: 0 90vh; /* 👈 */
    }
    
    @keyframes shrink {
      from { height: 100vh; }
      to { height: 10vh; }
    }
    
    #coverheader {
      position: sticky;
      top: 0;
      animation-name: shrink;
      animation-timeline: body-tl;
    }

    By defining the offsets on the ScrollTimeline itself, the entire ScrollTimeline is limited to the range 0 - 90vh. What if the authors want to animate on scroll outside of that range (e.g. from 90vh to 100%)? This is not possible with this approach, unless authors are able to define multiple ScrollTimelines on the same element.

  2. Allow scroll as a (faux) phase with <length-percentage>

    Following the way ViewTimeline phases are defined, a scroll phase could be introduced. That way there still is 1 set of keyframes and 1 ScrollTimeline. In the keyframes, authors can target several parts of the timeline by prefixing that phase to the keyframe offsets.

    body {
      scroll-timeline: body-tl block;
    }
    
    @keyframes shrink {
      scroll 0 { height: 100vh; }  /* 👈 */
      scroll 90vh { height: 10vh; }  /* 👈 */
    }
    
    #coverheader {
      position: sticky;
      top: 0;
      animation-name: shrink;
      animation-timeline: body-tl;
    }

    Authors would need to explicitly target the (faux) scroll phase if they want to use it with a ScrollTimeline. Instead of accepting only <percentage>s as the keyframe offset, <length>s would now also be valid here.

    One of the cool things about the whole scroll-linked animations concept is that you can use regular keyframes without needing to target any phase. If wanted, maybe, it could be so that “no phase implies the scroll phase” when used with a ScrollTimeline?

    @keyframes shrink {
      0 { height: 100vh; } /* When used linked to a ScrollTimeline, this would imply the scroll phase */
      90vh { height: 10vh; } /* When used with a DocumentTimeline animation, this would be invalid as it’s no <length> */
    }
  3. Introduce animation-timeline offsets

    A third option would be to introduce the scroll-offsets on the animation-timeline level. There would be two properties: animation-timeline-start and animation-timeline-end, with a <length-percentage> as their allowed value.

    body {
      scroll-timeline: body-tl block;
    }
    
    @keyframes shrink {
      from { height: 100vh; }
      to { height: 10vh; }
    }
    
    #coverheader {
      position: sticky;
      top: 0;
      animation-name: shrink;
      animation-timeline: body-tl;
      animation-timeline-offsets: 0 90vh;  /* 👈 */
    }

    This approach keeps the ability to define 1 ScrollTimeline on a an element and also to target parts of it when linking an animation. However, authors would need to attach two animations/keyframes when targeting various offsets.

    #coverheader {
      animation-name: shrink, otheranimation;  /* 👈 */
      animation-timeline: body-tl, body-tl;  /* 👈 */
      animation-timeline-offsets: 0 90vh, 90vh 100%;  /* 👈 */
    }

    One of the key things that ViewTimeline introduced, was the ability for authors to define 1 set of keyframes which can target all different phases if needed. This approach with animation-timeline-offsets does not offer this.

  4. Something else?

@bramus bramus added the scroll-animations-1 Current Work label Aug 8, 2022
@flackr
Copy link
Contributor

flackr commented Aug 9, 2022

This feels very similar to issue #7296 though I like some of the suggestions to handle this in a way similar to the way enter/exit phases are handled for ViewTimeline (See #7044). Following that thread, I think rather than offsets we could use whatever we decide the new shorthand for specifying start and end delay to set the range of the animation, e.g.

#coverheader {
  animation-delay: 0 90vh, 90vh 100%; /* Same as setting startDelay to 0 and 90vh respectively and endDelay to 90vh and 0 respectively. */
}

@ydaniv
Copy link
Contributor

ydaniv commented Aug 9, 2022

Yes, since we already decided, at least for now, that these are properties of the animation, and not of the timeline. So these should go, as @flackr said above, on the animation property as startDelay and duration/endDelay.

Though this still makes @bramus's no. 2 suggestion valid, at least conceptually, with regard to the @keyframes extension.

@bramus
Copy link
Contributor Author

bramus commented Aug 9, 2022

The extra added phase would leave the path for future additions open. Say a HoverTimeline were to be added, then it’s only a matter of adding a hover phase.

When no explicit phase is defined in the keyframes, the phase could be implied from the usage: adding non-phased keyframes to a ScrollTimeline? Use those “regular” keyframes. Adding keyframes that have a scroll phase to a ScrollTimeline? Use those scroll keyframes, ignoring the non-phased keyframes.

@bramus
Copy link
Contributor Author

bramus commented Sep 21, 2022

Some authors who have been playing around with the polyfill have raised similar issues, asking about offsets no longer being available.

  1. ScrollTimeline offsets are no longer respected after last update. flackr/scroll-timeline#64
  2. scrollOffset not working anymore flackr/scroll-timeline#76

The recent Motion One scroll library that enables JS-based Scroll-Linked Animations also offers this ability.

As @flackr suggested above, it could be achieved by having animation-delay-start and animation-delay-end accept lengths as their value.

  • animation-delay-start = [ <time> | <timeline-range-name> <percentage> | <length> ]
  • animation-delay-end = [ <time> | <timeline-range-name> <percentage> | <length> ]

@flackr
Copy link
Contributor

flackr commented Sep 27, 2022

FWIW I was thinking allowing lengths or percentages for ranges would allow greater flexibility:

animation-delay: [ <time> | <timeline-range-name>? [<percentage> | <length>]]+

Then you could use calculations within ranges, e.g.

/* Starts 10px after entering until 10px before done entering. */
animation-delay: enter 10px enter calc(100% - 10px);

@bramus
Copy link
Contributor Author

bramus commented Sep 27, 2022

Oh yes, great tweak! I like it!

@bramus
Copy link
Contributor Author

bramus commented Sep 28, 2022

@fantasai Could we get input from you on this before the spec goes to FPWD? Would love to get this back in there before the spec moves forward.

@meyerweb
Copy link
Member

FWIW I was thinking allowing lengths or percentages for ranges would allow greater flexibility:

Then you could use calculations within ranges, e.g.

I like the idea of adding length-percentages to animation-duration and animation-delay, particularly since viewport units could then be used.

@fantasai
Copy link
Collaborator

A few questions:

  • When a length delay or duration is applied to a time-based animation, what does it resolve to?
  • When a time delay is applied to a length-based animation, what happens? Do we create lag in the animation or ignore it or...?
  • If an offset applied to a range is outside the range (outside 0%-100%), do we clamp it or not?

@ydaniv
Copy link
Contributor

ydaniv commented Nov 2, 2022

  • When a length delay or duration is applied to a time-based animation, what does it resolve to?
  • When a time delay is applied to a length-based animation, what happens? Do we create lag in the animation or ignore it or...?

I don't think this use-case is relevant to consider. As I suggested in #7944, time for delay and duration only make sense for time-based animations and length makes no sense there. And vice versa, if the animation has a timeline which isn't time-based, duration is irrelevant (since it's always 100%), and time for delay makes no sense.
So we could ignore delay in this case and only parse the ranges (or use default values for ranges).

If an author wants to include both in @keyframes to be used for either case they could write it as follows:

@keyframes fade-in {
  0%, enter 20% {
    opacity: 0;
  }
  100%, enter 100% {
    opacity: 1;
  }
}

@fantasai
Copy link
Collaborator

fantasai commented Nov 2, 2022

I don't think this use-case is relevant to consider.

It doesn't matter if it's a use case or not, the behavior needs to be defined.

@ydaniv
Copy link
Contributor

ydaniv commented Nov 2, 2022

It doesn't matter if it's a use case or not, the behavior needs to be defined.

Yes, what I mean is that IMO these cases, where length is applied to time-based animations and time applied to length-based animations, should be treated as invalid and ignored.

  • If the animation has a timeline that's length-based then it should only accept length values - ignore duration and delay and only accept ranges.
  • If the animation is time-based, i.e. animation-tlmeline resolved to auto, then it should only accept time values as it does now, and ignore ranges.

This should also remove ambiguity from animation-delay and resolve the confusion with animation-range which currently only serves as an alias.

@fantasai
Copy link
Collaborator

fantasai commented Nov 7, 2022

@ydaniv We can't make property parsing conditional on the value of another property. :) So we have to do something different, either zeroing out the mistyped values or treating the properties as having their initial value or something.

@fantasai
Copy link
Collaborator

fantasai commented Nov 7, 2022

To summarize, I think we've got the following proposals up for debate:

  • Add <length-percentage> to animation-delay and animation-duration
  • Length delays resolve to 0s when applied to time-based animations and vice versa. (Percentage components are maintained intact.)
  • Length-based durations are ignored (treated as initial value) when applied to time-based animations, and vice versa.
  • Offset values are not clamped within their declared range.

@birtles Interested in your take on this discussion!

@birtles
Copy link
Contributor

birtles commented Nov 19, 2022

To summarize, I think we've got the following proposals up for debate:

  • Add to animation-delay and animation-duration

  • Length delays resolve to 0s when applied to time-based animations and vice versa. (Percentage components are maintained intact.)

  • Length-based durations are ignored (treated as initial value) when applied to time-based animations, and vice versa.

  • Offset values are not clamped within their declared range.

@birtles Interested in your take on this discussion!

Thanks for including me and sorry for the delay (I was away last week and forgot to update my GitHub status).

I'm afraid I haven't been following the scroll animation discussion very closely so my input is probably not particularly valuable. Two very high-level notes, however:

  1. An Animation is intended to be the vehicle that maps a static effect onto a timeline so extending the animation as in option 3 from the original list of options would be the most natural fit from an architectural point of view.

    Because animation-delay maps onto an effect it feels a little misaligned to me (i.e. the effect was supposed to be a "dumb", static, stateless thing agnostic of how it is used), but see the next point.

  2. When we started out with scroll-linked animations, we were under the assumption that it would be desirable to dynamically switch between a time-based timeline and a scroll-based one (e.g. when the scroll passed some threshold, the author would use JS to swap out the timeline to a time-based one, letting the animation run to completion).

    Introducing different units to animation-delay and animation-duration such that some units are ignored depending on the type of timeline doesn't seem to be compatible with that assumption (or with the notion that effects are independent of how they are used), but maybe we've determined it's no longer an important use case?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [scroll-animations-1] Bring back Scroll Offsets.

The full IRC log of that discussion <dael> Rossen_: This is a fairly long issue
<Rossen_> Initial Proposals Summary: https://github.com//issues/7575#issuecomment-1207786782 Key follow-up comments: https://github.com//issues/7575#issuecomment-1209635142 https://github.com//issues/7575#issuecomment-1253314529 Second Proposals Summary: https://github.com//issues/7575#issuecomment-1306103577 Key follow-up comments: https://github.com//issues/7575#[CUT]
<dael> Rossen_: You can follow initial proposals and key follow-ups from there ^
<dael> bramus: With the previous iteration of scroll linked animations that use scroll linked timelines and this is not in the re-write
<birtles> q+
<dael> bramus: A few suggestions, 8 Nov comment from fantasai summeries. Add a length % for naimation delay and animation duration. That way you can drive scroll linked animation over spec distance
<dael> Rossen_: On this side of the pond the comment is on Nov 7
<Rossen_> ack freereyes
<Rossen_> ack birtles
<dael> birtles: I'm not opposed to adding the different units to delay. Concern I raised is architectural. From API PoV there's 3 piecens, timeline, animations, effects. In css animation is blurred where delay is part of effect.
<dael> birtles: Architecturally would like effect separate so you can reuse it. That was the initial idea for the API.
<dael> birtles: I was a little concerned about putting in a delay because that's part of effect and makes it harder to reuse
<flackr> q+
<dael> birtles: One thought I just had there is another issue about overlap between animation range and delay. Was wondering if there's a possiblity to use animation range for this and have animation range apply to animation and animation delay apply to the effect. If we could satisfy the use case though that. Just a thought
<dael> bramus: That would still allow % for length but not delay
<Rossen_> ack flackr
<dael> birtles: I wondered if it applies to animation not effect architecturally more suitable
<dael> flackr: I think this does make use cases possible. I don't have any objection to it. Only concern is that delay does have units and it's time and they don't convert to the timelines of the effects. Have architectural breakage no matter which way we go. Not opposed, but don't think can avoid mixing units
<dael> birtles: I think % have slightly different case to vh units. If you can have effects defined in terms of % that's more reusable. If you have an effect that interpolates between these values over a range in the abstract and than animation maps to concrete.
<dael> birtles: % units and the general case of lengths I'm not opposed. nice if authors can achieve this without painting into a corner where they can't reuse the effect
<flackr> q+
<Rossen_> ack fantasai
<dael> fantasai: Two comments. 1 in terms of % I think % and absolute units need to be mixed. Sometimes you want absolute shift and sometimes you want relative and we combine. I don't think only % would work
<dael> fantasai: I think before we resolve we should jump to next issue, discuss, and then bring those decisions to this
<dael> flackr: You were concerned about resuability. The length values when used on a time-based timeline compute to 0 so the value are as effective as if they're in separate property. I think it's as resuable either way except you can't have a separate time-based delay
<birtles> q+
<Rossen_> ack fantasai
<dael> flackr: Also think delay is times so we will have to support % and times. It's hard to have a single unit world
<dael> birtles: With regards to fantasai point of absolute and relative I agree. We have absolute and relative times if we have %
<dael> birtles: Regards to reusability, on the original proposal there were 3 suggestions put forward. The third you can see the keyframes is un-effected. I guess that's an example of what I mean by reusable. It's only the second where keyframes change so maybe not important
<dael> bramus: In the 3rd example that uses animation timeline offsets?
<dael> birtles: Yes
<bramus> https://github.com//issues/7575#issuecomment-1207786782
<dael> birtles: I was saying it's possible to use a % on an effect and an absolute unit on the mapping at the animation level so you can have lengths, 90 vh on the animation, and then map to % on effect so you can combine absolute units with % without introducing diff length types
<Rossen_> q?
<flackr> q+
<Rossen_> ack flackr
<dael> flackr: In a previous breakout session and then with the group we resolved to have range-based offsets in keyframes which is laso a modification to keyframe spec that is incompat with a time-based animation
<dael> flackr: Based on a strong dev demand to have animation with entry and exit effect that are dynamic calc of points in scroll
<birtles> q+
<dael> flackr: Feel like that ship has sailed a bit to keep everything as %
<dael> flackr: I think for simple animations you will be able to reuse them. For things linked to position on length-based timeline it's not portable
<dael> birtles: yeah, maybe ship has sailed. Would be nice to have animation tied to mapping, but maybe too late
<dael> birtles: Other thing is was thinking with this use case we could realize without going further. But maybe say that's how things work now. Fair enough
<Rossen_> ack fantasai
<dael> fantasai: My suggestion is pause the convo, switch to next topic. I think a couple of these ideas are linked to next topic
<dael> Rossen_: We can do that unless everyone feels we're getting toward resolution
<dael> Rossen_: I see birtles moved himself along
<dael> birtles: If next issue is related we should do that first

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [scroll-animations-1] Bring back Scroll Offsets, and agreed to the following:

  • RESOLVED: Add length % to animation-range to be used as offsets
The full IRC log of that discussion <flackr> q+
<dael> Rossen_: Let's see if we can resolve on this one
<dael> flackr: Given that animation-range specifies the range the animation runs in, if we add length as well I think it solves use case and don't need lengths added to delay
<Rossen_> ack flackr
<birtles> q+
<dael> birtles: I think that's good. Good to push it down the road and consider how it interacts with group effects
<dael> fantasai: Prop: Add length % to animation-range to be used as offsets
<dael> Rossen_: Objections?
<dael> RESOLVED: Add length % to animation-range to be used as offsets
<birtles> ("Pushing it down the road" here refers to adding lengths to animation-delay)

@ydaniv
Copy link
Contributor

ydaniv commented Feb 3, 2023

A question regarding the resolution above, does it mean that the value of animation-range can be :

  1. <animation-range-name> <length-percentage>?
  2. <animation-range-name> <percentage> OR <length-percentage>?

If it's 1 then we have an ambiguity issue here.

FYI @fantasai @flackr

@bramus
Copy link
Contributor Author

bramus commented Feb 22, 2023

I was under the impression we decided that <length-percentage> can be added to a <animation-range-name> (for use with ViewTimeline), but that it could also be use without a <animation-range-name> (for use with ScrollTimeline). So yeah, needs some clarification to see what exactly we resolved on.

@ydaniv
Copy link
Contributor

ydaniv commented Feb 23, 2023

@bramus unless I'm missing something, but from what I can see range names have no use with ScrollTimeline. ScrollTimeline should be using simple <length-percentage> for duration and/or offsets, which we resolved on using ranges instead of delays - since delays have time values.

@bramus
Copy link
Contributor Author

bramus commented Mar 2, 2023

My original request for this issue was to be able to run a scroll-driven animation over a certain distance (in case of the header example: as you scroll the page from 0 to 90vh). The way I interpret the resolution, is that it would now be possible to do this as follows:

@keyframes shrink {
  from { height: 100vh; }
  to { height: 10vh; }
}

#coverheader {
  position: sticky;
  top: 0;
  animation-name: shrink;
  animation-timeline: scroll(); /* 👈 Will find the root scroller */
  animation-range: 0 90vh; /* 👈 Animation will run when scrolling from 0vh to 90vh */
}

If that’s incorrect, then the resolution from #8298 (comment) might offer a solution, as it calculates the timeline ranges differently now. IUC correctly, the combined outcome would allow this:

@keyframes shrink {
  from { height: 100vh; }
  to { height: 10vh; }
}

#coverheader {
  position: sticky;
  top: 0;
  animation-name: shrink;
  animation-timeline: view(self); /* 👈 Track myself */
  animation-range: exit 0 exit 90vh; /* 👈 This works because of #8298 */
}

Maybe @flackr or @fantasai can clarify?

@ydaniv
Copy link
Contributor

ydaniv commented Mar 2, 2023

If the header is stuck at top: 0 then the way I see it is:

In the first example:

#coverheader {
  position: sticky;
  top: 0;
  animation-name: shrink;
  animation-timeline: scroll();
  animation-range: 0 90vh;
}

Will start the animation at scrollY=0 and continue until scrollY=90vh.

In the second example:

#coverheader {
  position: sticky;
  top: 0;
  animation-name: shrink;
  animation-timeline: view(self);
  animation-range: exit 0 exit 90vh;
}

Regarding the range start, animation won't start running while the header is stuck, because it's still in contain range.
Only when it starts exiting, it starts shrinking.
As for the range end, I'm not sure we have a clear definition of what exit 90vh means? Is that the same as exit 0% + 90vh? - 90vh?
I think we need to resolve on #8054 to answer that.

@flackr
Copy link
Contributor

flackr commented Mar 10, 2023

@bramus you are correct, the intent is to allow both with or without an animation-range as an alternative to a percentage on non-time based timelines. i.e. your first example should work.

@flackr
Copy link
Contributor

flackr commented Mar 10, 2023

As for the range end, I'm not sure we have a clear definition of what exit 90vh means? Is that the same as exit 0% + 90vh? - 90vh? I think we need to resolve on #8054 to answer that.

exit 90vh is equivalent to exit calc(0% + 90vh).

@ydaniv
Copy link
Contributor

ydaniv commented Mar 10, 2023

@flackr great! But then I think we have an ambiguity here, see #7575 (comment). Should I open a new issue for this?

@flackr
Copy link
Contributor

flackr commented Mar 10, 2023

Sorry perhaps I'm just a bit slow today but can you explain the ambiguity? What's an example? Happy to see a new issue for that if you don't mind filing it.

fantasai added a commit that referenced this issue Mar 11, 2023
* Add <length> offsets to timeline range offsets
* Add <length-percentage> values referencing the whole timeline
* Tighten up definitions
@fantasai
Copy link
Collaborator

Fixed in 43b12e4 ; @bramus @flackr, let me know if I missed anything.

@ydaniv
Copy link
Contributor

ydaniv commented Mar 11, 2023

@fantasai I've added comments in the commit on specific lines.

@fantasai
Copy link
Collaborator

@ydaniv Replied. OK to close the issue?

@ydaniv
Copy link
Contributor

ydaniv commented Mar 14, 2023

@fantasai yes, thanks!

@fantasai fantasai removed this from Blocking/Urgent in Agenda Scratchpad Mar 28, 2023
Scroll linked animations [scroll-animations] automation moved this from Needs Edits to Done Mar 28, 2023
@fantasai fantasai added the Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. label Mar 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed Accepted by CSSWG Resolution Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. scroll-animations-1 Current Work
Projects
November 30 2022
Scroll Animations
Development

No branches or pull requests

7 participants