'GSAP scrolling breaks when switching browser tabs

I've noticed some strange behavior of GSAP scrolling in GatsbyJS. I have a container with full-page sections that are scrolled with GSAP.

I open a tab in a browser and go to my website. The scrolling works fine. Then I open a new tab and go to (let's say) google.com and spend some time on that website. The tab with my website is still open in a background. Then I switch from google tab back to my website tab. After doing that GSAP 'breaks' and scrolls two full-page sections one after another. Even if I scroll a mouse wheel a bit. And sometimes GSAP can't scroll the section at all. It looks like a full-page starts moving but suddenly the scrolling stops and GSAP places the current section to it's place.

I never go to any other website within that browser tab. Also I never go to any another route of my website. I just open an index page -> switch to another browser tab -> and switch back to my website tab. I have no idea how and why but exactly these actions cause the problem.

P.S. resizing the browser window helps but after some time the scrolling breaks again

Code:

export default function IndexPage() {
  useEffect(() => {
    gsap.registerPlugin(ScrollTrigger)
    gsap.registerPlugin(ScrollToPlugin)

    const sections = document.querySelectorAll("section")

    const scrolling = {
      enabled: true,
      events: "scroll,wheel,touchmove,pointermove".split(","),
      prevent: e => e.preventDefault(),
      disable() {
        if (scrolling.enabled) {
          scrolling.enabled = false
          window.addEventListener("scroll", gsap.ticker.tick, { passive: true })
          scrolling.events.forEach((e, i) =>
            (i ? document : window).addEventListener(e, scrolling.prevent, {
              passive: false,
            })
          )
        }
      },
      enable() {
        if (!scrolling.enabled) {
          scrolling.enabled = true
          window.removeEventListener("scroll", gsap.ticker.tick)
          scrolling.events.forEach((e, i) =>
            (i ? document : window).removeEventListener(e, scrolling.prevent)
          )
        }
      },
    }

    function goToSection(section, anim, i) {
      console.log(scrolling.enabled)

      if (scrolling.enabled) {
        // skip if a scroll tween is in progress
        scrolling.disable()

        gsap.to(window, {
          scrollTo: { y: section, autoKill: false },
          onComplete: scrolling.enable,
          duration: 1,
        })

        anim && anim.restart()
      }

      console.log(section)
    }

    sections.forEach((section, i) => {
      const intoAnim = gsap.from(section.querySelector(".right-col"), {
        yPercent: 50,
        duration: 1,
        paused: true,
      })

      ScrollTrigger.create({
        trigger: section,
        start: "top bottom-=1",
        end: "bottom top+=1",
        onEnter: () => goToSection(section, intoAnim),
        onEnterBack: () => goToSection(section),
      })
    })

    return () => {
      ScrollTrigger.kill()
    }
  }, [])

  return (
    <div className={styles.container}>
      <Header />
      <Products />
      <Contact />
      <Footer />
    </div>
  )
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source