Jump to content

Evans Hunt

ScrollTrigger using pin with ScrollTo to handle snap behaviour - Pinning issue

Recommended Posts



I am creating a multi-panel scrolling widget using the GSAP ScrollTrigger and ScrollTo plugins. When scrolling past the 2nd panel, I use ScrollTrigger to pin an SVG, and ScrollTo to override the snapping behaviour. I'm encountering a slight jump on the initial pinning of my SVG and am not sure what the cause is or how to alternatively smooth this out. My Codepen example isn't too bad, but still noticeable, and if i were to add more content the jump/glitch becomes more prominent.


The Codepen example is identical to my project's widget markup and styling. If there are any questions or context needed, I can provide it in this thread.






See the Pen rNpyexw by hichamtahaeh (@hichamtahaeh) on CodePen

Link to comment
Share on other sites

Welcome to the forums @Evans Hunt


I'm wondering if this code might be better for something like that.


// this scrolling object just allows us to conveniently call scrolling.enable(), scrolling.disable(), and check if scrolling.enabled is true.
  // some browsers (like iOS Safari) handle scrolling on a separate thread and can cause things to get out of sync (jitter/jumpy), so when we're animating the scroll position, force an update of GSAP tweens when there's a scroll event in order to maintain synchronization)
  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) {

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

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

      anim && anim.restart()


  sections.forEach((section, i) => {
      trigger: section,
      start: "top bottom-=1",
      end: "bottom top+=1",
      onEnter: () => goToSection(section, intoAnim),
      onEnterBack: () => goToSection(section),



Link to comment
Share on other sites

  • 2 weeks later...

Hello @OSUblake, sorry for the late reply!

The above code definitely helped out my widget a lot, but i'm just wondering what the intoAnim object is referencing on the onEnter callback?



Link to comment
Share on other sites

Oh, it was something I accidentally copied and pasted from another demo. You can pass in an animation instance to that gotoSection function and it will restart it.  

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.