Detect when scrolling has finished when using `scroll-behavior: smooth`

Use a debounce function as wrapper

"use strict";

var count = 0;
// The [trigger] anchors should trigger listening on scrollend
document.addEventListener('click', e => {
  if (e.target.matches('a[trigger]')) {

    // listen to CustomEvent 'scroll' only once
    window.addEventListener('scrollend', function(e) {
      console.log('Scrolling has finished', ++count)
    }, {
      once: true
    })

  }
});


{
  // create the scrollend event
  const options = {
    passive: true
  }
  const scrollEnd = debounce(e => {
    e.target.dispatchEvent(new CustomEvent('scrollend', {
      bubbles: true
    }))
  }, 100)

  window.addEventListener('scroll', scrollEnd, options)
}

// simple debounce
function debounce(callback, wait) {
  var timeout;
  return function(e) {
    clearTimeout(timeout);

    timeout = setTimeout(() => {
      callback(e);
    }, wait);
  }
}
html {
  scroll-behavior: smooth;
}

section:target {
  background-color: lightgray;
}

div {
  overflow: auto;
  height: 40px;
}

#totop {
  position: fixed;
  right: 10px;
  bottom: 50px;
  padding: 10px;
  background-color: rgba(255, 155, 255, 0.9);
}
<a name="top"> </a>
<div id="totop"><a trigger href="#top">to top</a></div>
<ul>
  <li><a trigger href="#_1">anchor 1</a></li>
  <li><a trigger href="#_2">anchor 2</a></li>
  <li><a trigger href="#_3">anchor 3</a></li>
  <li><a trigger href="#_4">anchor 4</a></li>
  <li><a trigger href="#_5">anchor 5</a></li>
  <li><a href="#_6">anchor 6 (no trigger)</a></li>
  <li><a href="#_7">anchor 7 (no trigger)</a></li>
  <li><a href="#_8">anchor 8 (no trigger)</a></li>
  <li><a href="#_9">anchor 9 (no trigger)</a></li>
  <li><a href="#_10">anchor 10 (no trigger)</a></li>
</ul>

<section id="_1">
  <h1>Lorem, ipsum dolor.</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nesciunt quibusdam eius possimus est sit iusto mollitia a molestias aperiam quam corrupti in culpa labore odit totam quod molestiae harum aliquid reiciendis, necessitatibus provident quasi laborum
    explicabo ad. Recusandae, ea esse!</p>
  <p>Natus doloremque voluptatem quas hic deleniti iusto, eaque sit aspernatur! Itaque modi voluptate placeat iure quam mollitia quod ipsum ea dolorem animi quis quisquam incidunt dignissimos cumque soluta cupiditate rem odio qui illo, ad provident explicabo
    impedit reprehenderit. Autem, obcaecati.</p>
</section>
<section id="_2">
  <h1>Omnis, sit libero!</h1>
  <p>Cumque repellat nesciunt quaerat, perferendis vel optio veritatis similique eum enim at recusandae velit asperiores debitis. Temporibus ratione voluptatem eum sequi voluptates, nihil, fugit, aut labore aliquam sapiente quam quod dolores. Veritatis voluptatem
    saepe aspernatur quia aperiam quaerat a impedit.</p>
  <p>Harum sunt explicabo repellat deleniti nesciunt, suscipit accusamus blanditiis architecto, voluptatum cupiditate optio quisquam sint, sed dignissimos a itaque eveniet libero in ut non eligendi quibusdam aut delectus? Repellendus consequatur amet unde
    maiores eaque ad, minima illo quis iusto inventore?</p>
</section>
<section id="_3">
  <h1>Veritatis, non commodi.</h1>
  <p>Rerum inventore quisquam nostrum, obcaecati, repudiandae ducimus cumque sed dicta corporis blanditiis neque, adipisci est porro earum reprehenderit! Facere, corrupti aliquid. Quae dolore placeat, corrupti in harum itaque odit inventore, nam perspiciatis
    expedita accusamus est quo illum fuga fugiat! Ipsam!</p>
  <p>Repellendus voluptatem optio placeat dolor quis expedita, dignissimos similique provident delectus ex laboriosam libero, fugiat esse. Fugiat ipsum quasi hic. Culpa, illum. Temporibus sunt earum fugit quo expedita asperiores sequi, eveniet culpa suscipit
    eum quas quos in ad vel? Odio.</p>
</section>
<section id="_4">
  <h1>Est, doloribus? Quia.</h1>
  <p>Perspiciatis accusantium nihil consectetur, beatae nulla doloremque error voluptas vitae, nobis, rem asperiores sit quibusdam corporis! Deserunt, veniam, ipsam placeat illo dolorem odio ducimus quo, facere tenetur commodi provident soluta nihil a minus
    doloremque fugit suscipit itaque quasi. Officiis, totam?</p>
  <p>Quibusdam reiciendis, deleniti placeat vero cum magnam, laudantium, veniam eius a laboriosam omnis accusamus delectus maiores labore doloremque voluptatum asperiores libero error vitae molestiae inventore eaque quam! Doloribus et, delectus, doloremque
    minima temporibus, velit explicabo corrupti quod magnam inventore neque.</p>
</section>
<section id="_5">
  <h1>Ducimus, tempore omnis?</h1>
  <p>Doloremque sequi nostrum exercitationem accusamus nemo voluptate vitae perferendis ipsam cumque voluptas vel molestias praesentium, necessitatibus voluptates sed officia veritatis eum a rem tenetur nisi. Possimus alias fugit illo consequuntur, asperiores
    tempora error, dignissimos assumenda culpa earum, eum voluptatum ex.</p>
  <p>Natus saepe neque rem corrupti quos a quis assumenda omnis hic accusamus eum eius, labore accusantium aperiam earum soluta beatae id, recusandae nesciunt! Natus commodi omnis non eum nemo maxime magnam provident, sint repellendus nulla adipisci? Odio
    officia assumenda qui!</p>
</section>
<section id="_6">
  <h1>Quo, expedita omnis.</h1>
  <p>Molestiae consectetur enim laborum sed tempora culpa, doloribus, suscipit ullam rerum exercitationem voluptas commodi nesciunt, modi fugit non provident consequatur. Quas delectus dolores, nemo rem qui unde fugiat inventore! Recusandae consequuntur
    eum placeat qui a ratione libero dignissimos ipsum quam.</p>
  <p>Officiis nostrum totam dolore neque iusto? Aperiam quia nemo aut omnis quibusdam similique ea ex. Assumenda blanditiis recusandae, iusto esse aut perferendis nulla sed quidem commodi porro, consequatur doloremque repellat. Assumenda quae quaerat consequuntur
    necessitatibus incidunt reiciendis libero architecto adipisci.</p>
</section>
<section id="_7">
  <h1>Ratione, quos officiis!</h1>
  <p>Qui ipsam cumque quae, quas provident, aliquid eius exercitationem aspernatur in voluptatum ut dolorem corrupti consequuntur ad voluptatibus inventore placeat hic molestias reiciendis! Delectus, quis asperiores! Molestias voluptatum ipsa dolores impedit
    labore nisi animi vel sapiente, cupiditate itaque minima commodi!</p>
  <p>Quia fugit, odio, quibusdam minima a error voluptate eligendi laudantium id pariatur, blanditiis sint non tenetur corrupti perspiciatis? Dolorum officiis minima obcaecati velit explicabo, voluptate error vitae repellat nostrum natus reiciendis voluptatum
    dolore earum eaque nemo incidunt numquam quae culpa!</p>
</section>
<section id="_8">
  <h1>Cum, porro atque!</h1>
  <p>Numquam corrupti nesciunt sit amet harum rem. Incidunt ea fugiat provident cumque corrupti, maiores aut esse, recusandae vero repellat ipsum nesciunt minus illum excepturi, soluta nemo veritatis rerum voluptas impedit similique perferendis amet? Eius
    dicta mollitia tempora, fuga ex maiores?</p>
  <p>Esse explicabo aliquam adipisci iure repellat ipsum laborum illo tenetur quae quas! Assumenda magni expedita provident veritatis fugit necessitatibus quod impedit maxime quibusdam. Nesciunt tempora dolores labore asperiores dolorem quidem, ex iste ipsa,
    recusandae, esse impedit iure ratione maxime fugiat?</p>
</section>
<section id="_9">
  <h1>Veritatis, neque molestias!</h1>
  <p>Sequi sapiente eligendi laudantium quos qui possimus repudiandae quis laborum modi facilis alias, consectetur natus, minima placeat commodi temporibus quae illo a sint? Omnis ipsa, dolore, praesentium at quisquam aliquid animi odio eius iusto magnam
    doloremque ab aspernatur itaque sequi.</p>
  <p>Iure facilis repellat possimus voluptatum. Recusandae voluptatibus vitae voluptates doloremque explicabo esse iure quo corporis error, cumque assumenda atque laborum neque. Quo non laboriosam nesciunt, vitae suscipit exercitationem repudiandae sunt
    assumenda sed saepe. Quo dignissimos, incidunt veritatis ratione ut quis?</p>
</section>
<section id="_10">
  <h1>Culpa, magni dolorem!</h1>
  <p>Quae, praesentium sit veritatis incidunt eligendi a ut at quas animi amet corrupti. Dignissimos modi tempore ratione et dolores. Pariatur facere beatae vero qui laudantium, asperiores consequatur quo officia excepturi atque, deserunt repudiandae, minus
    ex? Esse in non nihil laboriosam.</p>
  <p>Quod sit nihil eum doloribus deleniti possimus ducimus corporis vero exercitationem et? Vitae veniam, hic repellat placeat deserunt voluptatibus, eius animi natus in quibusdam quia nesciunt sint non quod, molestias minus! Minus excepturi inventore fugit
    beatae quas quod tenetur similique?</p>
</section>

The only feasible option appears to be to just wait until there aren't any more scroll events:

let timer;
window.addEventListener( 'scroll', () => {
    clearTimeout( timer );

    timer = setTimeout( () => {
        callback();
    }, 300 );
}, { passive: true } );

Tags:

Javascript

Css