scroll-into-view / scroll-into-view-if-needed

Element.scrollIntoView ponyfills for things like "if-needed" and "smooth"

Home Page:https://scroll-into-view.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature Request]Add onScrollEnd callback

zheeeng opened this issue · comments

Wish there is an 'onScrollEnd' callback it will be used to set some state / trigger some events after the scrolling finished.

Note: there is an upcoming proposal to the scrolling spec:
w3c/csswg-drafts#1562 (comment)

The logic in this library would need to account for both browsers that start implementing the new spec, and the majority of browsers who don’t.
I have to research and find a stable way to detect that a smooth-scrolling operation has completed. It’s a bit challenging since you have to account for two edge cases where browser performance can create false negatives:

  • a smooth scrolling operation that was interrupted by the user starting to scroll in a different direction.
  • a scroll operation completed, but the user have already started scrolling further by the time the JS code is able to query scroll coordinates (this happens a lot on mobile devices, especially iOS)

It's a huge challenge.

Challenging but also extremely important for accessibility! For accessibility we often have to manage focus, which causes its own scroll events, BUT the native focus has no way of accounting for things like sticky headers or any of the positioning that is possible with this library (and gradually becoming possible through standards). Currently in order to have the necessary scroll modifications (block positioning, manual offset, etc) we need to call the focus function AFTER the scroll function is complete (since it has 'if-needed' built in, if it's called after the scrolling it doesn't change the document scroll position)

It seems that if the focus fires in the middle of the smooth-scroll, it cancels the scrolling, but unfortunately it seems to also cancel the native behaviour (it doesn't move the document scroll position to the focused element like would happen natively... but this may be a weird consequence of both using scroll-behavior: smooth) 😑

So... it's necessary to know whether the scrolling is complete before firing the focus function. I'm currently computing the scrolling distance to base a setTimeout on if browser supports smooth-scroll, but it is not an ideal solution.. though based on the caveats @stipsan noted above, it may be as good as it gets for now 😔

I keep wanting to use standards but they keep letting me down and I end up wishing I was using javascript animation.. but hard to do that without performance.

There is another nice thing I found (that may start working better soon in most browsers..) which is that in Chrome you can call element.focus({preventScroll: true}). Presumably other browsers will add support soon.

I think the approach you describe (immediately cancelling the native scroll behaviour for focus and doing your own -- without the transition complication) is probably the best all around. We don't have many transitions right now but i can definitely anticipate that becoming a problem :|

I have recently been reading that in a lot of cases JavaScript animations can be more performant than native css transitions so that makes me feel better about maybe just switching to the smooth- version of this lib if it has a callback option!

I think the reliability piece is probably worth the potential performance overhead. It makes me a bit batty trying to think of how to provide reusable components that will manage focus properly while also working whether or not a user has added scroll-behavior: smooth to their document 😬