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] Should range of ViewTimeline be clamped to scrollable range? #7432

Closed
flackr opened this issue Jun 29, 2022 · 8 comments

Comments

@flackr
Copy link
Contributor

flackr commented Jun 29, 2022

As the spec for ViewTimeline doesn't include the formula to determine the current time it's not clear what the current expected behavior is when the element cannot scroll fully out of view / into view.

E.g. For a header which starts partially in view such as the parallax header on the scroll timeline polyfill demo, should the animation start at 0% even though the element has already almost left the scrollport, or should it start at the element's current progress through the scrollport (e.g. ~70% since it's about to start scrolling offscreen)?

My opinion is clamping to the actually scrollable range is likely to produce the more expected result, but wanted to ensure we have an open issue to track this until the spec includes the formula / touches on this issue.

@flackr flackr added the scroll-animations-1 Current Work label Jun 29, 2022
@fantasai
Copy link
Collaborator

fantasai commented Jul 6, 2022

I think the effect we should pin our timeline design to is the “fade-in/fade-out” effect. If you want to schedule things to fade in as they scroll onto the screen, and fade out as they scroll off, what kind of effect do you want if the element is half-visible above the fold? Probably not fully transparent, right?

If we need additional behaviors for other use cases, we can add them, but I think that's the one we should be addressing by default.

@flackr
Copy link
Contributor Author

flackr commented Jul 11, 2022

I think what you've proposed (the starting at the element's current offset) is reasonable and arguably simpler to work with. There are many cases where clamping to the scroll range is unintuitive and so I'm good with not clamping being the default.

The parallax header example is a case where without clamping it's much more complex for the developer - i.e. the user will never see the full range specified in the animation. If you look at the unclamped version of my above linked demo you can see how the parallax header starts shifted down since it's already scrolled almost all the way through the view.

@flackr
Copy link
Contributor Author

flackr commented Jul 25, 2022

One way we could eventually add support for clamped range animations without specifically adding a clamp parameter is to make a way to specify clamped phases or just the clamped phase of a timeline.

E.g. Given the following:

<div id="scroller" style="overflow: auto; height: 200px">
  <div id="title" style="height: 50px;">Title</div>
  <div id="header" style="height: 100px;"></div>
  <div style="height: 1000px;"
</div>

Producing roughly the following layout where the header is half the height of the scrollport starting 50px down in the middle:

   #scroller
   -----------------
  |  Title          |
  |   ---------     |
  |  | #header |    |
  |  |         |    |
  |   ---------     |
  |                 |
   -----------------

The unclamped ViewTimeline will start at 50% (when #scroller has scrollTop = 0) and progress to 100% (when #scroller has scrollTop = 150. This means with a naive translation (to shift the header down as you scroll down), it will start shifted down from its initial position.

We could support these particular cases without needing a clamped attribute on the timeline by adding a clamped / reachable (bikeshed) phase which corresponds to the actually reachable portions of the view timeline (i.e. in this case 50% to 100%).

@flackr flackr added the Agenda+ label Jul 25, 2022
@bramus
Copy link
Contributor

bramus commented Jul 26, 2022

+1 for unclamped. Otherwise demos like https://codepen.io/bramus/pen/xxRZZdK – where the child elements end up halfway in the scroller, thus at 50% animation progress, when reaching the scrollport edges – would no longer be possible.

About the parallax header you mentioned: that one seems more like a use-case for exit keyframes applied onto the .header?

@keyframes adjust-header {
  exit 0% { transform: none; }
  exit 100% { transform: translateY(30%); }
}

.header {
  view-timeline: tl-header block;
}

.header .background {
  animation: adjust-header tl-header;
}

Or am I overlooking things?

@flackr
Copy link
Contributor Author

flackr commented Jul 26, 2022

I intentionally had the header not quite at the top of the page in my example, as I think in that case the author would want the parallax effect to start immediately, but cover the entire range of motion. I.e. you could imagine a common bit of CSS (not yet accelerated but could be in the future) which would apply parallax to oversized background images:

@keyframes parallax-keyframes {
  from { background-position: bottom; }
  to {background-position: top; }
}
.parallax {
  animation: parallax-keyframes view-timeline()
}

Where view-timeline is a hypothetical syntax for an anonymous view-timeline similar to scroll(). This class could then be applied to any element having an oversized background image resulting in a parallax which (with clamped range) would cover the entire visible range of the image regardless of where on the page the element was.

Anyways, I agree that unclamped should be the default behavior, and I'm not sure this particular case is even important enough to solve now. I was mostly just pointing out that we can easily add a phase to support this use case in the future if it seems important.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Should the range of ViewTimeline be clamped?, and agreed to the following:

  • RESOLVED: ViewTimeline progress is not clamped by scrollable range
The full IRC log of that discussion <TabAtkins> Topic: Should the range of ViewTimeline be clamped?
<TabAtkins> github: https://github.com//issues/7432
<TabAtkins> flackr: In ViewTimeline, if the subject you'e observeing is at the top of the page it starts in view, and you can never scroll to a position where it's "start".
<TabAtkins> flackr: Does it start part of the way thru the animation, or do we clamp the range?
<TabAtkins> flackr: There are use-cases for entry/exit where it's clearly better to not clamp the range
<TabAtkins> flackr: Slightly better for parallax if we do
<TabAtkins> flackr: But think it's possible to produce a clamped range from an unclamped, but can't do the latter reasonably
<TabAtkins> flackr: So I propose we don't clamp the range. In the future we can consider another phase or something if we do need to address this.
<TabAtkins> Makes sense to me
<fantasai> +1 to optimizing for fade-in/fade-out type animations
<TabAtkins> astearns: Is the range clamping a discoverable thing?
<TabAtkins> flackr: Not clamping is the easier thing for devs to reason about
<TabAtkins> flackr: Clamping means suddenly your produced times change if your element is near the beginning or end of the scroller
<TabAtkins> flackr: It's completely observable what time you get and if it's clamped or not
<TabAtkins> flackr: Could be exposed if we had a start and end scorll offset; the offsets would be negative
<ydaniv> q+
<TabAtkins> flackr: Dont' rmemeber if we have that or not, we might
<astearns> ack ydaniv
<TabAtkins> ydaniv: Not sure I follow on clamping
<TabAtkins> flackr: It means you'd always be able to reach the full range of the animation
<TabAtkins> flackr: So if the element started in view it would start at 0% and progress to 100% as it scrolled out of view
<TabAtkins> flackr: I think it's more confusing to do that
<TabAtkins> flackr: It complicates the relationship between position and animation progress
<TabAtkins> ydaniv: So if I have an enter animation, but the element starts halfway on screen
<TabAtkins> ydaniv: So if you clamp, I'd still start at 0% and progress the whole animation?
<TabAtkins> flackr: Right
<bramus> +1 on not clamping
<TabAtkins> flackr: Whereas uhnclamped it would start at 50% of the entry phase, matching the progress
<TabAtkins> ydaniv: For me, not clamping is the natural way to go
<TabAtkins> ydaniv: So like fade-in/fade-out, if my element is already in the displayed area...
<TabAtkins> flackr: Think there might be a conflation of scroll-trigger and scroll-driven animations
<TabAtkins> flackr: So if the element is halfway in, unclamped would make it half faded in
<TabAtkins> flackr: There are a few places where clamping is useful, if you do want the full set of keyframes available.
<TabAtkins> flackr: Example in the issue - an oversized image and I want it to transition from topmost to bottommost.
<TabAtkins> flackr: If it starts onscreen you can use an exit animation anyway
<TabAtkins> ydaniv: So I vote for not clamping and maybe creating a clamp mechanism later, since it seems like extra magic
<TabAtkins> flackr: Yeah that's the proposal. I don't think we should make the clamp mechanism yet, until we see use-cases.
<TabAtkins> astearns: So proposed resolution is that ViewTimeline progress is not clamped to the scrollable range
<TabAtkins> RESOLVED: ViewTimeline progress is not clamped by scrollable range

@fantasai
Copy link
Collaborator

fantasai commented Sep 7, 2022

Clarified. @flackr Lmk if that seems to cover it, or if you think further clarification is necessary.

@flackr
Copy link
Contributor Author

flackr commented Oct 5, 2022

Looks good, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants