Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
andiwi

ScrollTrigger in nextjs build not working reliably

Go to solution Solved by Cassie,

Recommended Posts

Hi @all,


thank you for this awesome library! Unfortunately, I am facing issues with the ScrollTrigger effect inside my nextjs production build. I hope you can help me.

 

The ScrollTrigger effect works perfectly fine, when I start the nextjs project in development ("next dev"). However, when I build a production build and host the production build via a web server, the element to which the ScrollTrigger effect is attached to is not displayed from time to time.

 

I created a simple codesandbox where you can reproduce the behaviour: https://codesandbox.io/s/nextjs-gsap-scrolltrigger-bug-qtgfl?file=/pages/index.js It works fine inside the codesandbox (development) but when built and deployed to a server https://csb-qtgfl-nml1dj1ep-andiwi.vercel.app/ the headline is not displayed from time to time. To reproduce go to https://csb-qtgfl-nml1dj1ep-andiwi.vercel.app/ and refresh the page multiple times until the headline is not displayed anymore. 

 

I followed the official resources https://greensock.com/react/ and https://greensock.com/st-mistakes/ and also read through forum posts like https://greensock.com/forums/topic/27012-scrolltrigger-and-array-of-refs-in-react/ but did not find a solution for the problem.

 

I am new to gsap. Do you spot any wrong usage of the library? The same setup works in a simple react app (e.g. create-react-app). Would be great if you have any ideas how to solve this error. I am trying to solve the error for days now without any success and I am out of ideas.

 

Thank you!

 

 

 

 

Link to comment
Share on other sites

Hey there!

 

I would first try using useLayoutEffect instead of useEffect.

Also - console.log(h1Ref.current)  in your useLayoutEffect - see if you can work out what the difference is between reloads.

Link to comment
Share on other sites

Thank you for your quick response. I tried to use useLayoutEffect. However, when using the useLayoutEffect hook, the ScrollTrigger effect does not work at all.

Here is the example: https://codesandbox.io/s/nextjs-gsap-scrolltrigger-bug-uselayouteffect-vxxd9?file=/pages/index.js
Deployed: https://csb-vxxd9-andiwi.vercel.app/

EDIT: Indeed, what I can observe is that the console.log output is sometimes different, but the bug occurs in both cases. It looks like the DOM is not ready when gsap effect is initialised. 

console.log output (example 1):
image.thumb.png.70205700c48cbb6a6520dd5a45491443.png

console.log output (example 2):
image.thumb.png.7da9c82926210c13a7f456b66481c4a3.png
 

Link to comment
Share on other sites

This example seems to work on codesandbox. Not sure why it wouldn't be working for you?


I don't think you need to be killing the animation, and you had paused:trueset which isn't needed on a scrollTriggered animation. It will be paused anyway until it hits the trigger point.

https://codesandbox.io/s/nextjs-gsap-scrolltrigger-bug-uselayouteffect-forked-eu2v9?file=/pages/index.js

Link to comment
Share on other sites

Thank you for the hints. I removed the paused:true and the animation cleanup (although on this page a cleanup is recommended: https://greensock.com/react/#cleaning-up )

Yes, it works on codesandbox (which is the development setup), but when I build and deploy the production build the headline is not displayed.

Link to comment
Share on other sites

Your console.log statements show that GSAP is animating, but I have no idea why it's not visible. I would try another test animation, like say something else that doesn't use .from() or opacity for a sanity check.

 

Link to comment
Share on other sites

I just tested a gsap.from and a gsap.to with and without opacity animation (without scrollTrigger). 
For example:

useLayoutEffect(() => {
    gsap.from(h1Ref.current, {
      rotation: 45,
      y: 200,
      duration: 1,
      opacity: 0, // also tested without this line
    });
  }, []);

All examples are working fine in production build. Maybe an issue in the scrollTrigger plugin?

EDIT: I also tested the same effect with my scrollTrigger which works fine with a gsap.to but when using the gsap.from in combination with scrollTrigger the animation doesn't get played correctly. So it might be a bug of scrollTrigger in combination with a gsap.from ?

 

useLayoutEffect(() => {
    gsap.to(h1Ref.current, { // gsap.to is working fine, gsap.from -> not working 
      scrollTrigger: {
        id: 1,
        trigger: h1Ref.current,
        start: "top bottom",
        toggleActions: "play none none reverse",
      },
      rotation: 45,
      y: 200,
      duration: 1,
      opacity: 0, // also tested without this line
    });
  }, []);

 

Edited by andiwi
additional info
Link to comment
Share on other sites

I doubt it because this shows the h1 is being animated. See the inline opacity and transform style.

 

image.png

 

I also noticed that you are animating the trigger, which you shouldn't do as that will mess up ScrollTrigger's calculations. Try animating a wrapper element instead.

 

  • Like 1
Link to comment
Share on other sites

I set the trigger to a wrapper div. Unfortunately, this didn't solve the issue. Is setting the trigger to the to-be-animated element bad in general when using ScrollTrigger with a gsap.from? I just followed the simple example of https://greensock.com/docs/v3/Plugins/ScrollTrigger 

 

What is interesting: when I wrap the gsap animation into a timeout to push it to the JS event loop, the animation at least gets played most of the time, but still not every-time (refresh browser multiple times until the animation gets stuck again). So there might be some race condition between DOM painting of react/nextjs static rendering optimization and gsap initialisation.

Example with scroll trigger on a wrapper div:  

 

EDIT: I once again tested the code with simple react -> also not working: https://codesandbox.io/s/react-gsap-scrolltrigger-not-working-gy3kn

Edited by andiwi
add simple react example
  • Like 1
Link to comment
Share on other sites

  • Solution

Ah yes! Got it. Looks like it's down to a regression in the latest version.

So sorry about this @andiwi 

Fixing options! 

  • Step back the version to 3.8
  • Use the latest beta 
  • Fix it for the current version by setting lazy: false on your .from() tween(s). 

 

 

 

  • Like 4
Link to comment
Share on other sites

Ah! @Cassie, you are my hero! 😊👏 Also many thanks to @OSUblake for helping here.

Where can I buy you a cup of coffee?

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

Oh no don't worry about that. Very happy to help! ☺️ Thank you for the kind offer though.

To answer this too...
 

Quote

I set the trigger to a wrapper div. Unfortunately, this didn't solve the issue. Is setting the trigger to the to-be-animated element bad in general when using ScrollTrigger with a gsap.from

 

It's a bad plan if you're going to be moving the trigger element as it can mess up calculations - if you're just doing an opacity fade it'll be fine.

  • Like 3
Link to comment
Share on other sites

  • 2 months later...

Great! I had exactly the same issue and had a hard time finding a topic about it.

I solved it by upgrading gsap to the beta version: yarn add gsap@latest

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.
×