Skip to content

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

Description

@bramus

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.

Activity

  1. ydaniv commented on Aug 7, 2022

    @ydaniv
    Member

    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?

  2. ydaniv commented on Aug 7, 2022

    @ydaniv
    Member

    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?

  3. bramus commented on Aug 8, 2022

    @bramus
    ContributorAuthor

    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?

  4. flackr commented on Aug 9, 2022

    @flackr
    Contributor

    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. */
    }
  5. ydaniv commented on Aug 9, 2022

    @ydaniv
    Member

    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.

  6. bramus commented on Aug 9, 2022

    @bramus
    ContributorAuthor

    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.

  7. bramus commented on Sep 21, 2022

    @bramus
    ContributorAuthor

    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> ]
  8. flackr commented on Sep 27, 2022

    @flackr
    Contributor

    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);
  9. bramus commented on Sep 27, 2022

    @bramus
    ContributorAuthor

    Oh yes, great tweak! I like it!

  10. bramus commented on Sep 28, 2022

    @bramus
    ContributorAuthor

    @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.

  11. meyerweb commented on Oct 27, 2022

    @meyerweb
    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.

  12. fantasai commented on Oct 31, 2022

    @fantasai
    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?
  13. ydaniv commented on Nov 2, 2022

    @ydaniv
    Member
    • 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;
      }
    }
  14. 19 remaining items

  15. flackr commented on Mar 10, 2023

    @flackr
    Contributor

    @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.

  16. flackr commented on Mar 10, 2023

    @flackr
    Contributor

    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).

  17. ydaniv commented on Mar 10, 2023

    @ydaniv
    Member

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

  18. flackr commented on Mar 10, 2023

    @flackr
    Contributor

    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.

  19. fantasai commented on Mar 11, 2023

    @fantasai
    Collaborator

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

  20. ydaniv commented on Mar 11, 2023

    @ydaniv
    Member

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

  21. fantasai commented on Mar 13, 2023

    @fantasai
    Collaborator

    @ydaniv Replied. OK to close the issue?

  22. ydaniv commented on Mar 14, 2023

    @ydaniv
    Member

    @fantasai yes, thanks!

  23. added
    Commenter SatisfiedCommenter has indicated satisfaction with the resolution / edits.
    on Mar 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions