Jump to content


ScrollTrigger pinning does not behave as expected in combination with nuxt 3 and page transitions after page switch

Go to solution Solved by Rodrigo,

Recommended Posts

Hi everybody,

First of all, thanks for all these awesome Tools! I have been using gsap for a while and I am amazed.

But now I am struggeling to get the scrolltrigger to work in nuxt 3. Everytime I switch a page, the scrolltrigger animation breaks. When I a disable the page transitions, the scrolltrigger animations are working again. When I set "pin" to false, the animations are also working again after the page switches. It seems like the combination of pin set to true and the page transitions are breaking the animation.

I modified a codesandbox to simulate the problem: 


Thanks in advance for any help or assistance!

Link to comment
Share on other sites

Hi Cassie,

thanks for the quick response.

I used one of these templates to demonstrate the problem. But I couldn’t find a possible solution for this specific case. 

i would be happy to hear from @Rodrigo!

Link to comment
Share on other sites



I've been looking at this in different examples (Nuxt, Vue, React, Next) for hours and I'm totally lost. This happens only when changing routes and it works as expected in codepen:

See the Pen GRByLvw by GreenSock (@GreenSock) on CodePen


Honestly I can't think of a single reason beyond routing for this, but I simply don't know how it generates. Maybe this could be related to the history API or something else this routing solutions use. Among the many things I tried, I wrapped each box in a new element and setting pinSpacing to false and the same keeps happening 🤷‍♂️


Perhaps @GreenSock can think of something or can spot the issue. Maybe the issue is quite simple but is eluding me.


Please stand by.

Happy Tweening!

Link to comment
Share on other sites

thank you for your great effort!
I also recognized that this issue disappears, when I include ScrollSmoother. But the performance (especially) on mobile devices suffers from it and the pinned animations become glitchy/jumpy

  • Thanks 1
Link to comment
Share on other sites

I also tried replicating this issue in vue to see if its just nuxt related, but when I am again setting pin to true in my ScrollTrigger, the animations break. 


I would be happy for any kind of help! Thanks in advance!

Link to comment
Share on other sites



I'm dealing with the same issue even just using VUE 3

Link to comment
Share on other sites

Hi everyone!


I'm still looking into this since, as I mentioned before, goes beyond the Vue/Nuxt ecosystem as we're seeing the same behaviour on React/Next as well.


So far I tried different animations and different versions of GSAP with the same result. We'd appreciate enormously if you could make some tests on your own, if you can spare some minutes to do so of course. No need to re-write anything as we understand that time doesn't grow on trees, just small things and if you stumble upon anything that makes a difference (even if it doesn't solve it) let us know so we can have a look.


Thanks for your patience and please stand by.

Happy Tweening!

Link to comment
Share on other sites

  • Solution



The issue is due to the type of animation being applied to the main container of the page. Routing/Transition libraries normally demand that there has to be only one element to be animated. Hence we wrapped everything in a single DOM node. The animation we're using actually applies transforms to that element which causes issue with pinning in ScrollTrigger. 



There are two possible solutions for this.

  1. Use pinReparent on all your ScrollTrigger instances that reside inside a transformed parent or set a default for all ScrollTrigger instances:
      pinReparent: true,
  2. If using that approach is not an option what you could do is on the transitions configuration remove all the styles applied by GSAP on the element being animated:
    const onEnter = (el, done) => {
      gsap.set(el, { autoAlpha: 0, scale: 0.8, xPercent: -100 });
          paused: true,
          onComplete() {
            // Removes all styles (including transforms)
            // once the page/route transition is completed
            gsap.set(el, { clearProps: "all" });
        .to(el, { autoAlpha: 1, xPercent: 0, duration: 0.25 })
        .to(el, { scale: 1, duration: 0.25 })

Both options are equally valid and should work without any issues.


Hopefully this solves the issues you've been experiencing. If you have any other question/issue let us know.

Happy Tweening!

  • Like 3
  • Thanks 2
Link to comment
Share on other sites

Hey Rodrigo, this works perfectly! Thank you very much for this great effort!

  • Like 1
Link to comment
Share on other sites

Nice one Rodrigo! 

  • Thanks 1
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.