DEV Community

Wahid
Wahid

Posted on

1

How to Fixing GSAP ScrollTrigger Pin Issue in React

When working with GSAP ScrollTrigger in React, you might encounter an issue where your pinned section disappears when scrolling from the top but works correctly when scrolling from the bottom. This issue usually happens due to improper cleanup or React's strict mode behavior.

Problem

  • The section disappears when scrolling down.
  • The pin works only when scrolling up.
  • The .pin-spacer div is created incorrectly, affecting layout.

Solution
To fix this, we need to properly structure our GSAP animation using gsap.context() and ensure the cleanup process is handled correctly.

*Step-by-Step Fix
*

  1. Create a Separate Animation File
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

export const useInspireAnimation = (sectionRef) => {
  if (!sectionRef.current) return;

  const ctx = gsap.context(() => {
    gsap.to(sectionRef.current, {
      scrollTrigger: {
        trigger: sectionRef.current,
        start: "top top",
        end: "+=100%",
        scrub: true,
        pin: true,
        markers: true, // Remove after debugging
      },
    });

    gsap.fromTo(
      sectionRef.current.querySelector("h1"),
      { opacity: 0, y: 50 },
      {
        opacity: 1,
        y: 0,
        duration: 1,
        ease: "power2.out",
        scrollTrigger: {
          trigger: sectionRef.current,
          start: "top 80%",
          end: "top 50%",
          scrub: true,
        },
      }
    );
  });

  return () => ctx.revert(); // Cleanup GSAP context when c

Enter fullscreen mode Exit fullscreen mode
  1. Implement in the Component
import { useEffect, useRef } from "react";
import { useInspireAnimation } from "./useInspireAnimation";

const InspiringSection = () => {
  const sectionRef = useRef(null);

  useEffect(() => {
    const cleanup = useInspireAnimation(sectionRef);
    return cleanup;
  }, []);

  return (
    <section
      ref={sectionRef}
      className="section-2 h-screen w-screen bg-gray-900 text-white flex items-center justify-center"
    >
      <h1 className="text-4xl font-bold">Section 2</h1>
    </section>
  );
};

export default InspiringSection;
Enter fullscreen mode Exit fullscreen mode

Why This Works?

  1. Ensures proper cleanup: Using ctx.revert() removes previous animations when the component unmounts.
  2. Uses gsap.context(): Prevents unexpected behavior in React Strict Mode.
  3. Prevents issues with pin-spacer: Ensures the pinning doesn't cause layout bugs.
  4. Keeps the animation separate: Improves maintainability and readability.

Final Thoughts
Using this method, you can prevent your pinned section from disappearing while maintaining smooth scroll-based animations in GSAP. If you're still facing issues, try adding ScrollTrigger.refresh() after a small delay to ensure GSAP recalculates the layout correctly.

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️