Chrome nettleser, Nyheter

Scrollend, a new JavaScript event

Before the scrollend event, there was no reliable way to detect that a scroll
was complete. This meant that events would fire late or while a user’s finger
was still down on the screen. This unreliability in knowing when scroll has
actually ended, led to bugs and a poor experience for the user.

Before

document.onscroll = event => {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}

The best this setTimeout() strategy can do is know if scroll has stopped for
100ms. This makes it more like a scroll has paused event, not a scroll has
ended event.

After the
scrollend
event, the browser does all this difficult evaluation for you.

After

document.onscrollend = event => {}

That’s the good stuff. Perfectly timed and packed full of meaningful conditions
before emitting.

Browser support


chrome preview, Preview

👁
firefox 109, Supported

109
edge, Not supported

×
safari, Not supported

×

Source

Try it!

Event details

The scrollend event fires when:

  • The browser is no longer animating or translating scroll.
  • The user’s touch has been released.
  • The user’s pointer has released the scroll thumb.
  • The user’s keypress has been released.
  • Scroll to fragment has completed.
  • Scroll snap has completed.
  • scrollTo() has completed.
  • The user has scrolled the visual viewport.

The scrollend event does not fire when:

  • A user’s gesture did not result in any scroll positional changes (no translation occurred).
  • scrollTo() did not result in any translation.

A reason this event took so long to come to the web platform was due to the many
small details that needed specification details. One of the most complex areas
was articulating the scrollend details for the Visual
Viewport

versus the document. Consider a webpage that you zoom in on. You can scroll
around when in this zoomed state, and it’s not necessarily scrolling the
document. Rest assured that even this visual viewport user driven scroll
interaction will emit the scrollend event once it completes.

Using the event

Like other scroll events, you can register listeners in a couple ways.

addEventListener("scrollend", (event) => {
// scroll ended
});

aScrollingElement.addEventListener("scrollend", (event) => {
// scroll ended
});

or, use the event property:

document.onscrollend = (event) => {
// scroll ended
};

aScrollingElement.onscrollend = (event) => {
// scroll ended
};

Polyfills and progressive enhancement

If you’re looking to use this new event now, here’s our best advice. You can
continue using your current scroll end strategy (if you have one) and at the
beginning of it check support with:

'onscrollend' in window
// true, if available

That will report true or false depending if the browser offers the event. With
this check, you can branch the code:

if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll = event => {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}

That’s a healthy start to progressively enhancing your scrollend event when it
is available. You could also try a
polyfill
(NPM) I made that does the best
the browser can:

import {scrollend} from "scrollyfills"

// then use scrollend as if it's existed this whole time
document.onscrollend = callback

The polyfill will progressively enhance to use the browser built-in scrollend
event if available. If it’s not available, the script watches pointer events and
scroll to do the best estimation of the event ending it can.

Use cases

It’s a good practice to avoid computationally heavy work while scrolling is
happening. This practice ensures scrolling is free to use as much memory and
processing as it can to keep the experience smooth. Using a scrollend event
provides the perfect time to call out and do the hard work, because scrolling is
no longer happening.

The scrollend event can be used to trigger various actions. A common use case
is synchronizing associated UI elements with the position that the scroll
stopped. For example:

  • Syncing a carousel scroll position with a dot indicator.
  • Syncing a gallery item with its meta data.
  • Fetching data after a user scrolls to a new tab.

Imagine a scenario such as a user swiping away an email. After they finish
swiping you can then perform the action based on where they scrolled to.

You could also use this event for synchronizing after programmatic or user
scroll, or actions such as logging analytics.

Here’s a good example where multiple elements such as arrows, dots, and focus,
need to be updated based on the scroll position. Watch how I built this
carousel on YouTube
. Also, try
the live demo
.

Thanks to Mehdi Kazemi for their engineering work on this and Robert
Flack
for API and implementation guidance.

This post is also available in: English

author-avatar

About Aksel Lian

En selvstendig full stack webutvikler med en bred variasjon av kunnskaper herunder SEO, CMS, Webfotografi, Webutvikling inkl. kodespråk..