DEV Community

Cover image for Setting up GSAP's ScrollTrigger with Nuxt 3πŸ”§πŸš€
Fitra Rahmamuliani
Fitra Rahmamuliani

Posted on

Setting up GSAP's ScrollTrigger with Nuxt 3πŸ”§πŸš€

Introduction

Navigating the fusion of GSAP's ScrollTrigger with Nuxt 3 is an adventure filled with potential, but it's not without its share of obstacles. Many developers, myself included, have grappled with challenges ranging from hydration client mismatches to mystifying errors like "entry.5cb7c34d.js:20 GSAP target .partner-wrapper not found." Join me on this exploration as we unravel the intricacies and triumph over the roadblocks together.

The Initial Struggles

In the early stages of integrating GSAP's ScrollTrigger with Nuxt 3, many developers, including myself, encountered a series of challenges. From hydration client mismatches to perplexing errors like "entry.5cb7c34d.js:20 GSAP target .partner-wrapper not found," the road seemed daunting. To make matters worse, attempting to build and start the project resulted in a dreaded 500 error, persisting even in staging and production environments.

Error Hydration

Identifying the Solution

After extensive research, trial-and-error, and searching the solution in the gsap github issues, the solution to these issues finally emerged. The key lies in configuring Nuxt 3 to play nicely with GSAP's ScrollTrigger. Let's take a step-by-step look at the transformation.

Step 1: Update Nuxt Config

Before:



    '@nuxtjs/i18n',
    'nuxt-simple-sitemap',
    'nuxt-api-party',
    '@nuxtjs/google-fonts'
  ],

  pinia: {
    autoImports: ['defineStore']
  },


Enter fullscreen mode Exit fullscreen mode

After:



    '@nuxtjs/i18n',
    'nuxt-simple-sitemap',
    'nuxt-api-party',
    '@nuxtjs/google-fonts',
    '@hypernym/nuxt-gsap'
  ],

  gsap: {
    extraPlugins: {
      scrollTrigger: true,
      scrollTo: true
    }
  },

  pinia: {
    autoImports: ['defineStore']
  },


Enter fullscreen mode Exit fullscreen mode

Step 2: Refactor GSAP Imports

Before:



<script setup>
import gsap from 'gsap'
import { ScrollTrigger, ScrollToPlugin } from 'gsap/all'

gsap.registerPlugin(ScrollTrigger, ScrollToPlugin)


Enter fullscreen mode Exit fullscreen mode

After:



<script setup>
const { $gsap, $ScrollTrigger } = useNuxtApp()


Enter fullscreen mode Exit fullscreen mode

With these changes, your project should now be free from the dreaded 500 errors, and GSAP's ScrollTrigger should function seamlessly as intended.

Step 3: Make sure to call the gsap and ScrollTrigger using $ and inside onMounted

Before:



onMounted(() => {
  links.value = gsap.utils.toArray('ul.privacy-policy__sticky-nav li a')
  links.value.forEach(link => {
    const el = document.querySelector(link.getAttribute('href'))
    const linkST = ScrollTrigger.create({
      trigger: el,
      start: 'top'
    })

    ScrollTrigger.create({
      trigger: el,
      start: 'top 10%',
      end: '+=50%',


Enter fullscreen mode Exit fullscreen mode

After:



onMounted(() => {
links.value = $gsap.utils.toArray('ul.privacy-policy__sticky-nav li a')
links.value.forEach(link => {
const el = document.querySelector(link.getAttribute('href'))
const linkST = $ScrollTrigger.create({
trigger: el,
start: 'top'
})

<span class="nx">$ScrollTrigger</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
  <span class="na">trigger</span><span class="p">:</span> <span class="nx">el</span><span class="p">,</span>
  <span class="na">start</span><span class="p">:</span> <span class="dl">'</span><span class="s1">top 10%</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">end</span><span class="p">:</span> <span class="dl">'</span><span class="s1">+=50%</span><span class="dl">'</span><span class="p">,</span>
Enter fullscreen mode Exit fullscreen mode
Enter fullscreen mode Exit fullscreen mode




Conclusion:

The journey from troubleshooting GSAP's ScrollTrigger in Nuxt 3 to achieving a smooth, error-free integration can be challenging, but armed with the right knowledge and configuration, success is within reach. By following the steps outlined in this article, you can overcome the obstacles and bring delightful scroll-triggered animations to your Nuxt 3 project.

Happy coding and scrolling!

Top comments (2)

Collapse
 
rhernandog profile image
Rodrigo Hernando • Edited

Hi,

This is Rodrigo from the GSAP Team!

We'd like to know if you could share a repo that we can take a look at in order to help you with the issue(s) you're having.

I've created a simple demo using the latest versions of Nuxt and GSAP, using ScrollTrigger with pinning and I wasn't able to replicate any of the problems you mention in the article.

Repo:
github.com/rhernandog/nuxt3-scroll...
Deployment in Netlify:
nuxt-scrolltrigger-test.netlify.app/

Sometimes we see that a 500 error comes from the fact that a ScrollTrigger instance could be created outside an onMounted() hook, which makes total sense since there is no need to run GSAP code in the server.

Also hydration mismatching can stem from using pinning on your ScrollTrigger instances. In order t make pinning work ScrollTrigger adds a DOM element around the element being pinned, but that element is not present in the server when the page is rendered, so obviously the DOM structure doesn't match the one in the client. For that ScrollTrigger has a configuration called pinSpacer which allows you to use a node already present in the DOM for pinning:

<div id="myPinWrapper">
  <div class="content>
    <!-- YOUR CONTENT HERE -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode
onMounted(() => {
  gsap.to(".element", {
    rotation: 360,
    scrollTrigger: {
      trigger: ".content",
      start: "top top",
      end: "+=100%",
      pin: true,
      pinSpacer: "#myPinWrapper",
    },
  });
});
Enter fullscreen mode Exit fullscreen mode

In the demo I created I'm using pinning without the pinSpacer config option because I didn't ran into any hydration issue neither on development, building/preview and in the deployed app.

As mentioned it would be ideal to see a basic implementation that repeats the error you were having and if you like you can start a thread in our support forum and we can link that here as well so other users can benefit not only of your generosity by writing and sharing this article but also the discussion and solution of the issue(s) in our forums.

Best regards,
Rodrigo.

Collapse
 
fitrakun profile image
Fitra Rahmamuliani

Hi Rodrigo,

Thank you so much for your detailed response and for sharing your demo. I really appreciate your input and the time you took to help.

I did encounter the error you mentioned about the ScrollTrigger instance outside of the onMounted() hook, but I managed to resolve it using the steps outlined in the article. Ensuring GSAP code runs only on the client side within the onMounted() hook was indeed crucial.

Your pinSpacer configuration is very helpful and will definitely use it in future projects. Unfortunately, I can't share the project code as it is confidential. However, I hope the explanations in my article provide enough clarity for others facing similar issues.

Thanks again for your insights and assistance. It's great to connect with you through my article!

Best regards,
Fitra