Logo
Published on

How to Use GSAP With Next.js 14 and SSR Enabled

Authors
  • Name
    Twitter

Photo by Sander Sammy on Unsplash

If you’re facing difficulties integrating GSAP with Next.js, there’s good news.

This short how-to article will show you how to use GSAP with NextJs 14 SSR enabled. This way you will be able to keep all your SEO benefits while having fancy animations.

In case you are unfamiliar with GSAP. It is a library which enables you to make amazing animations on your website. Think Apple product landing pages.

See some examples here.

The Issue

The primary issue stems from Next.js’s server-side rendering, which typically doesn’t mesh well with animations.

To effectively use GSAP with Next.js, the key is to initially allow Next.js to serve a static site. Then, once the site is generated, you can add the sophisticated GSAP animations on the client side. This approach ensures that GSAP is limited to the client side, which is necessary for optimal functionality.

Solution

In Next.js, this can be achieved in the following way: we create a custom hook. This hook is designed to assess the environment in which the code is operating. This distinction is crucial to ensure that GSAP only activates in the appropriate context, aligning with the client-side environment.

export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect

Once you’ve created the helper file with your custom hook for handling GSAP in a Next.js environment, you can easily add animations to any component. Here’s how you can do it:

  1. Import the Custom Hook: Begin by importing the custom hook you’ve created in your helper file into the component where you want to add animations.
  2. Integrate the Hook: In your component, use the custom hook to determine if the code is running on the client side. This will ensure that GSAP animations are only activated in the appropriate environment.
  3. Implement GSAP Animations: Once you’ve confirmed that the code is running on the client side, you can proceed to implement your desired GSAP animations within the component.

Here is an example of it:

import { gsap } from 'gsap/dist/gsap'
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'

function PositioningOne() {
  const mainREf = useRef(null)
  const firstParagraphRef = useRef(null)

  useIsomorphicLayoutEffect(() => {
    // Ensure the refs are current before using them in gsap.context

    // Providing firstParagraphRef.current as the scope
    let ctx = gsap.context(() => {
      gsap.registerPlugin(ScrollTrigger)
      const tl = gsap.timeline()

      ScrollTrigger.create({
        animation: tl,
        trigger: mainRef.current,
        start: 'top top',
        markers: true,
        end: '+=2000',
        scrub: true,
        pin: true,
        anticipatePin: 1,
      })

      tl.fromTo(
        firstParagraphRef.current,
        { opacity: 0 },
        { opacity: 1, duration: 2, yPercent: -100 }
      )
      tl.to(firstParagraphRef.current, {
        opacity: 0,
        duration: 1,
      })
    }, [firstParagraphRef.current, mainRef.current]) // This is extremely important, you need to pass each ref into it

    // Cleanup function
    return () => ctx.revert()
  }, [])

  return (
    <section ref={mainREf}>
      <p ref={firstParagraphRef}>Hello there!</p>
    </section>
  )
}

Pay attention to the import statements, as they differ from traditional frameworks due to the unique nature of Next.js.

To incorporate GSAP functionality, it’s essential to add the custom hook to each component where you want animations.

Additionally, remember to utilize ref in your components. This helps Next.js maintain element consistency across server and client, ensuring smooth animation transitions.

Thanks for reading,
Matija