JavaScript: Detecting the end of native smooth scrolling

Updated . Posted . Visible to the public.

When you use native smooth scrolling there is no built-in method to detect the end of the scrolling animation. Methods like scrollTo() Show archive.org snapshot don't return a promise. We may eventually get a scrollend Show archive.org snapshot event, but that is still some time away Show archive.org snapshot .

Until then I'm using the following awaitScrollEnd() function as a workaround. It returns a promise that resolves when the given Document or Element does not receive a scroll event for 75 milliseconds:

import debounce from 'lodash-es/debounce'

function awaitScrollEnd(viewport, delay = 75) {
  return new Promise((resolve) => {
    function done() {
      viewport.removeEventListener('scroll', debouncedDone)
      resolve()
    }

    // We consider scrolling to have stopped after we haven't received
    // a `scroll` event for `delay` milliseconds.
    //
    // The default delay (75) assumes a minimum framerate of ~13 FPS
    // while scrolling.
    let debouncedDone = debounce(done, delay)
    viewport.addEventListener('scroll', debouncedDone, { passive: true })
    debouncedDone()
  })
}

Use it after you started a native scrolling motion:

element.scrollIntoView({ behavior: 'smooth' })
await awaitScrollEnd(document)
Profile picture of Henning Koch
Henning Koch
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2023-05-09 14:26)