Jump to content
Search Community

ScrollSmoother in Next.js breaks ScrollTrigger upon page navigation from ScrollSmoother page to non ScrollSmoother page

null test
Moderator Tag

Recommended Posts

Hi guys. 

 

Here is a minimal demo.  Clone it or download the .zip and place the Club Greensock gsap-bonus.tgz at the root and do npm install(as described here).

 

Then run npm run dev to run it.

 

Scroll down and see how there is a Scrolltrigger animation on the navbar.

 

Then, navigate to the page titled "parallax".  This page has ScrollSmoother on it.  The navbar ScrollTrigger animation does still work on this page.

 

Now, navigate to another page.  The ScrollScrolltrigger navbar animation is broken.

 

Then navigate to another page and it works again!

 

I have been troubleshooting this for a whole day and I cannot figure it out.

 

Can anyone help me?

 

If anyone knows how I can use ScrollSmoother plugin in a Codesandbox without exposing my Club Greensock .zip then I can create a Codesandbox demo so you don't have to install the npm packages locally.

 

Thank you in advance.

 

P.S. Scrollsmoother (and ScrollTrigger and all of GSAP) is AWESOME!

Link to comment
Share on other sites

Blake, your CodeSandbox starter is awesome and works fantastic.

 

But I must be using CodeSandbox wrong because every time I add anything it breaks with an "Internal Server Error".

 

It is not just when I add something to your CodeSandbox.  This error happens with every single CodeSandbox I try to use.

 

I have tried dozens over the last several days and I always get this error.

 

CodeSandbox is really neat and I really really want to be able to use it.

 

Can you please watch this video I recorded that shows me running into the error and let me know what I am doing wrong?

 

Thank you very much for the help.

Link to comment
Share on other sites

Wow, i did not realize that server icon was there on the side.  I was just refreshing the simulated browser and also refreshing the actual webpage and it did not fix the error even when I reverted back to the original working code.

 

That appears to have solved the issue!

 

One issue down.  Now I will port in my demo into the codesandbox.  :)

  • Like 2
Link to comment
Share on other sites

Yeah, I can edit it. I think one of the issues is that that nesting needs to be different, kind like this.

 

<div id="smooth-wrapper">
          <div id="smooth-content">
            <PageTransition route={router.asPath}>
              <Component {...pageProps} />
            </PageTransition>
          </div>
        </div>

 

And we need to kill some ScrollTriggers and effects when navigating to a new page. We also need to refresh ScrollSmoother on new routes. I just put it inside a timeout for now. How would I go about calling ScrollTrigger.refresh() at the end of the page transition?

 

It's looking better, but there are still issues with it, like that black area when you scroll down. Is that part of the wipe?

 

https://codesandbox.io/s/gsap-scrollsmoother-next-js-starter-forked-demo-459fmr?file=/pages/_app.js

 

I'm going to tinker around with make a ScrollSmoother component similar to what I did with this nuxt.js one. 

 

 

 

  • Like 2
Link to comment
Share on other sites

@OSUblake

 

Thank you for your help.  With your guidance we FINALLY got it working!!! :)

 

You were right, I needed to refresh the Scrolltrigger when the animation going into the next page is done - or at least refresh once the next page is visible.

 

Here is the demo.

 

The coolest part is that I now know how to use ScrollSmoother inside CodeSandbox!

 

Thank you very very very much.

 

  • Like 3
Link to comment
Share on other sites

Hey @null and @OSUblake.
Thanks a bunch for figuring this out. I am currently in the research phase for a new project we kicked off yesterday.
Your example basically answered all of my open questions for solving animation and page transitions in next.

I gotta say it really feels good seeing an engaged community and support team working together to create awesome projects.
Kinda forgot how that felt. Totally worth the money.

Thanks a lot!

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

For anyone passing by in the future.

There is a minor issue with the CodeSandbox example, where the "Jump to C" button stops working after navigating to a different route and back.
Calling the refresh() method of ScrollTrigger when executing the scrollTo callback fixes this.
I don't know if this is the best solution since I am a newbie myself.
Maybe @OSUblake is able to confirm this?
 

pages/index.js L:26

function scrollTo() {
  ScrollTrigger.refresh();
  smoother && smoother.scrollTo(boxC.current, true, "center center");
}


Happy coding, chimp

  • Like 1
Link to comment
Share on other sites

2 hours ago, chimp1nski said:

Calling the refresh() method of ScrollTrigger when executing the scrollTo callback fixes this.
I don't know if this is the best solution since I am a newbie myself.

 

Yep, that's what I mentioned above.

 

On 4/21/2022 at 5:04 PM, OSUblake said:

And we need to kill some ScrollTriggers and effects when navigating to a new page. We also need to refresh ScrollSmoother on new routes.

 

  • Like 1
Link to comment
Share on other sites

Nvm, I forked the "final demo" from null which is missing the cleanup you provided in your example.
Unforunately the sandbox you provided in the post you mentioned threw a runtime exception switching routes as well (smoother instance in the cleanup was undefined).

I think I fixed in this fork. Or at least it's a demo that works (for me) as intended (I guess).
GSAP ScrollSmoother + Next.js (starter) (forked) - DEMO - CodeSandbox

I am not too sure if this is the correct way to use gsap with Next / React but I searched far and wide to find a starter project / post about best-practices and this thread is the closest I could get.

  • Like 1
Link to comment
Share on other sites

Oh man I am starting to feel like one of those guys that somehow isn't able to browse the docs correctly and just asks questions that have already been answered years ago 😬

I'm truly sorry for that @OSUblake I really hope your not too annoyed of me already :D 

  • Like 3
Link to comment
Share on other sites

  • 9 months later...

Don't suppose anyone knows of a working example with Nextjs 13 App directory?

 

Having a similar issue where i create my ScrollSmoother in /app/layout.tsx, but when navigating to /page-1/, parallax doesn't work and also doesn't when navigating back to the root page /

 

Here's my /app/layout.tsx file:

 

"use client";

import { Manrope, Rock_Salt } from "@next/font/google";
import { PropsWithChildren, useRef, useState } from "react";
import Providers from "../redux/providers/providers";
import { gsap, ScrollSmoother } from "../utils/gsap";
import Navigation from "../ui/Navigation";
import { SmootherContext } from "../utils/SmootherContext";
import { useCorrectEffect } from "../utils/useCorrectEffect";

import Cta from "../ui/Cta";
import Footer from "../ui/Footer";
import PageShrinker from "../ui/PageShrinker";

import "styles/globals.css";

const manrope = Manrope({
  variable: "--display-font",
  weight: ["200", "300", "400", "500", "600", "700", "800"],
});

const rock_salt = Rock_Salt({
  variable: "--body-font",
  weight: ["400"],
});

const siteTitle = "";

type Props = PropsWithChildren;

export default function RootLayout({ children }: Props) {
  const app = useRef<HTMLDivElement>(null);

  const [smoother, setSmoother] = useState<ScrollSmoother | undefined>();

  useCorrectEffect(() => {
    let mm = gsap.matchMedia(app);

    mm.add("not (pointer:coarse)", () => {
      const smoother = ScrollSmoother.create({
        smooth: 1.5,
        effects: true,
      });

      setSmoother(smoother);
    });
  }, []);

  return (
    <html
      lang="en"
      className={`bg-black ${manrope.variable} ${rock_salt.variable}`}
    >
      <head>
        <title>{siteTitle}</title>
        <meta name="description" content={siteTitle} />
      </head>
      <body>
        <Providers>
          <Navigation />
          <SmootherContext.Provider value={smoother}>
            <div id="smooth-wrapper" ref={app}>
              <div id="smooth-content">
                <PageShrinker>{children}</PageShrinker>
                <Footer />
              </div>
            </div>
          </SmootherContext.Provider>
        </Providers>
        <noscript>
          <style>
            {`
              .invisible {
                visibility: visible !important;
              }
            `}
          </style>
        </noscript>
      </body>
    </html>
  );
}

 

Am i doing this in the wrong file?

Link to comment
Share on other sites

I'm not seeing any of the cleanup/refresh for route changes in this. I'm guessing this is likely the root of the issue, but it's really hard to tell what's going on, especially in a complex ecosystem like React, without a minimal working demo:

 

It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or CodeSandbox that demonstrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

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

 

If you're using something like React/Next/Vue/Nuxt or some other framework, you may find StackBlitz easier to use. We have a series of collections with different templates for you to get started on these different frameworks: React/Next/Vue/Nuxt.

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

  • 11 months later...
On 2/15/2023 at 5:36 PM, Rodrigo said:

Here is an example using the App folder with ScrollSmoother:

https://stackblitz.com/edit/nextjs-ysf649?file=app%2Fpage.js,app%2Fimages%2Fpage.js

@Rodrigo , this link is broken now. Can we get a working example of ScrollSmoother in Next App Directory with multiple pages? Maybe using useGSAP() hook? :) I have no idea how to tackle that correctly...

Link to comment
Share on other sites

Hi,

 

This is basically a misconception that a lot of developers have when it comes to the famous app router feature. The client components are all rendered on the server but then hydrated on the client (like Next did it for years with great results). For specific use cases and apps that heavily depend on server-side stuff (lots of initial requests, server-side data, query and data caching and others) the client components are there.

https://nextjs.org/docs/app/building-your-application/rendering/client-components

 

I challenge you to create two identical apps and make the layout a client component on one and a server component in another. Most likely the performance drop (if any) would be minimal and mostly unnoticeable to the naked eye, you'd have to run a very accurate benchmark in order to really know.

 

Now if for some reason you're seeing a considerable drop in performance, you can change the layout component in order to be fully rendered in the server and find a different approach in order to make this work and see if there is actually any benefit. On next apps using the pages router I never ran into serious performance issues due to initial rendering times, JS Kb size and such things, I worked in a couple of SaaS made in Next that relied heavily on the server and we used React Query, getStaticProps and getServerSideProps with excellent results. On regular static websites honestly I don't see the need for all this fuzz of the app router (and the inconveniences tied up to it [100% personal opinion here]) and that's why so many people are looking into other frameworks like Nuxt, SvelteKit, Astro and Remix (React alternative). The React and Next teams made it really hard and confusing for developers in order to get the benefits of SSR to be honest.

 

Just my two cents.

 

Happy Tweening!

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.
×
×
  • Create New...