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.
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']
},
After:
'@nuxtjs/i18n',
'nuxt-simple-sitemap',
'nuxt-api-party',
'@nuxtjs/google-fonts',
'@hypernym/nuxt-gsap'
],
gsap: {
extraPlugins: {
scrollTrigger: true,
scrollTo: true
}
},
pinia: {
autoImports: ['defineStore']
},
Step 2: Refactor GSAP Imports
Before:
<script setup>
import gsap from 'gsap'
import { ScrollTrigger, ScrollToPlugin } from 'gsap/all'
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin)
After:
<script setup>
const { $gsap, $ScrollTrigger } = useNuxtApp()
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%',
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>
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)
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:
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.
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 theonMounted()
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