DEV Community

Discussion on: Movement and Visibility Detection with CSS and JS πŸ‘€

Collapse
 
ingosteinke profile image
Ingo Steinke, web developer • Edited

How to prevent smooth scrolling triggering momentary visibility, making animations start too early, or even worse, causing the intended target scrolled out of view caused by layout shift after inserting elements that are larger than their original placeholder?

html {
    scroll-behavior: smooth;
}
Enter fullscreen mode Exit fullscreen mode
<a href="#lower">lower</a>
<p id="upper">...</p>
<p id="middle">(triggered unintentionally on scrolling over)</p>
<p id="lower">intended link target</p>
Enter fullscreen mode Exit fullscreen mode

I found two relevant StackOverflow questions, one is unanswered, the other suggests using a debounce technique trying to figure out if the user is there to stay. As you can see in my project code, I use a hash map to relate timeout IDs to DOM element IDs to prevent redundant function calls.

A helpful takeaway to learn: passing our IntersectionObserver entries to a timeout function, we can check again later if they are still visible. A timeout of 1 second seems more than enough to make sure that the smooth scrolling has finished and the elements that we only passed by are out of sight and not intersecting anymore.

How to prevent intersection observer from firing when passing over elements quickly with the debounce approach:

In the code example below, there is a button to scroll to the bottom of the page, passing over six observed divs.

isIntersecting fires for each element as they pass through the viewport. Is it possible to throttle or add a delay to the trigger to prevent the intersection event…

Avoid handle IntersectionObserver when use window.scrollTo with behavior smooth (unanswered):

I'm creating a landing page using nuxt, I use hash to indicate each route on my page, for this I'm using scrollBehavior to handle hash on route and scroll to section with smooth:

  router: {
    scrollBehavior: async (to, from, savedPosition) => {
      console.log(to, from, savedPosition)
      if (savedPosition) {
        return savedPosition;
…