Update April 3, 2023:
This is now on MDN and shipping in browsers:
- Firefox 109
- Chrome 114
Web developers often watch scroll events to synchronize ancillary elements, fetch data, trigger animations, and more. Today watching scroll events is done with the scroll
event. But if developers want to know when scroll has ended, or rested and isn't moving anymore, there currently is no event. To work around this, developers set a timeout and/or check scroll positions, to attempt an estimated scrollend event, like so:
element.addEventListener('scroll', () => {
clearTimeout(element.scrollEndTimer);
element.scrollEndTimer = setTimeout(synchronizeFn, 100);
});
The fastest this function can determine when scroll has ended is 100ms
. It's also quite wasteful as it overrides the previous timeout on every scroll tick. Browser engines don't like this waste and developers don't like this delay. Furthermore, this strategy will fire synchronizeFn()
if a user has scrolled with their finger and paused for 100ms, essentially prematurely firing the event because scroll hasn't changed, but the user isn't done.
tabs-scrollend.mp4
https://codepen.io/argyleink/pen/JjXoXVe
carousel-scrollend.mp4
https://codepen.io/argyleink/pen/jOzEpjG/e26504e41694bd6267469ba23effae30
determine-snapped.mp4
https://codepen.io/argyleink/pen/wveVPom/17a5b2ee3236403d369881d816b0f03d
A scrollend
event that takes into account user interaction, proper timing, and the visual viewport.
element.addEventListener('scrollend', () => {
synchronizeFn()
});