Jump to content
Search Community

Issue with GSAP ScrollTrigger: Horizontal scrolling animation not working as expected in Next.js project

Don AW test
Moderator Tag

Recommended Posts

I am working on a Next.js project where I am trying to implement a horizontal scrolling section using GSAP and ScrollTrigger. However, I am facing an issue where the horizontal scrolling animation is not working as expected. The subsequent content scrolls up immediately while the horizontal scroll is occurring. 

I have been troubleshooting this for quite a while but haven't been able to resolve the issue. I have also noticed that the scroller-start and scroller-end markers are being placed at the top right-hand corner of the screen, which seems incorrect.

I have created a simplified version of my setup on StackBlitz to illustrate the issue: https://stackblitz.com/edit/nextjs-7zxyqi?file=components%2FStylists.tsx


Here's the relevant code from my project:

 

// Stylists.tsx
import React, { useEffect, useRef } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

const images = [...]
const styles = {...}

const Stylists: React.FC = () => {
  const panelsContainerRef = useRef(null);

  useEffect(() => {
    const sections = gsap.utils.toArray('.panel');
    const sectionWidth = 420;

    const scrollTween = gsap.to(sections, {
      xPercent: -100 * (sections.length - 1),
      ease: 'none',
      scrollTrigger: {
        start: 'top top', // Offset start position
        trigger: panelsContainerRef.current,
        pin: true,
        pinSpacing: false,
        scrub: 1.23,
        snap: 1 / (sections.length - 1),
        // end
        end: () => '+=2000',
        markers: true,
      },
    });

    return () => {
      scrollTween.kill(); // Kill the GSAP animation
      ScrollTrigger.getAll().forEach((st) => st.kill()); // Kill all ScrollTrigger instances
    };
  }, []);

  return (
    <div style={styles.myContainer}>
      <div style={styles.panelsContainer} ref={panelsContainerRef}>
        <h2 style={styles.headerText}>OUR STYLISTS</h2>
        <div style={styles.flexContainer}>
          {images.map((image, index) => (
            <section style={styles.panel} className="panel" key={index}>
              <img
                src={image.src}
                alt={`Image ${index + 1}`}
                style={styles.image}
              />
              <div style={styles.textContainer}>
                <h4>{image.name}</h4>
                <p>{image.title}</p>
              </div>
            </section>
          ))}
        </div>
        <button>EXPLORE STYLISTS</button>
      </div>
    </div>
  );
};

Attempts to resolve the issue:

- Adjusted the start, end, trigger, pin, and other ScrollTrigger configuration options.
- Checked the HTML structure and CSS styles.
- Utilized the markers option in ScrollTrigger to visualize the trigger points and scroll regions.
- Tried simplifying the setup to isolate the problem.
- Tried 'gsap.context()' to encapsulate the GSAP animation and ScrollTriggers

- Tried 'useIsomorphicLayoutEffect' and 'useLayoutEffect'

- Downgraded to gsap version "3.8.0"

- Cleared browser cache


Additional Information:

OS: Ubuntu 22.04.3 LTS
Browser: Brave


I would really appreciate any insights or suggestions on how to resolve this issue. Thank you!

Link to comment
Share on other sites

Hi @Don AW and welcome to the GSAP Forums!

 

Thanks for being a Business user and supporting GSAP! 💚

 

Is not quite clear to me what exactly you're trying to do. The code in the demo you provided is working exactly as it should.

 

I don't see any problems with the markers. Keep in mind that you are telling ScrollTrigger that the animation should start when the top of the trigger hits the top of the viewport, so the markers being at the top is exactly where they should be.

 

As for the pinning there are two problems in your code.

  1. If you want the next element to wait and not show in the viewport while the element you're using as trigger is still pinned then removed the pinSpacing: false option from your config object. That basically tells ScrollTrigger that the element should remain in that position but the content after the element being pinned should not be pushed down. 
  2. You are pinning an element in your component that is not the outmost parent. That causes the element being pushed in an uneexpected way.

 

Here is a fork of your demo:

https://stackblitz.com/edit/nextjs-lhgtnk?file=pages%2Findex.js,components%2FStylists.tsx

 

Finally when using GSAP in React/Next always use GSAP Context:

https://gsap.com/resources/React

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Hi Rodrigo, 

Thank you so much for your help! 

I had added the pinSpacing: false after troubleshooting for awhile and just started blindly adding new properties to try and resolve the issue  :lol:never a good idea.. 

 

I also wasn't pinning the parent most element of the animated section so thank you for that insight.

 

Nonetheless, these changes alone didn't resolve the issue. 

 

Eventually, I figured out that the parent container on my homepage had flexbox settings applied via the class flex flex-col items-center.
These flexbox settings were affecting the layout of my components and, consequently, the behavior of the GSAP scroll animation.


Before: 

export default function Home(){
  
  <div className={`px-4 w-full flex flex-col items-center`}> // Flex Styles Causing the Issue
      <Hero />
      <SectionComponent/>

      {/* Stylists Section with Horizontal Scroll */}
      <OurStylists />       

      <SectionComponent/>
      <SectionComponent/>
      <SectionComponent/>
      <InfiniteBanner />
   </div>
  );
}


After: 
 

export default function Home(){
  
  <div className={`px-4`}> // Flexbox styles removed
     <Hero />
     <SectionComponent/>

     {/* Stylists Section with Horizontal Scroll */}
     <OurStylists />       

     <SectionComponent/>
     <SectionComponent/>
     <SectionComponent/>
     <InfiniteBanner />
   </div>
  );
}


Takeaway - CSS layout settings, such as flexbox, can have a significant impact on the behavior of animations and the layout of elements on the page :rolleyes:
Thanks again for your help! I'll make sure to use GSAP Context ;)
Kind regards,
Don

  • Like 1
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...