Tutorial
Using GSAP in React and Next.js
Render the markup with React, scope GSAP to the component, and clean up the animation when the component unmounts.
Let React render and GSAP animate
React should decide what exists on the page. GSAP should animate the elements after they exist. The clean boundary is: render semantic markup first, then use refs to tell GSAP which elements are allowed to move.
This separation avoids awkward code. GSAP should not build the component tree; it should animate the component after React renders it.
Scope every animation
In component-based apps, global selectors become fragile quickly. gsap.context lets you scope selectors to a specific root element and revert the animation cleanly when the component unmounts.
This matters in Next.js because route transitions, Fast Refresh, and conditional rendering can otherwise leave old animations or inline styles behind.
"use client";
import gsap from "gsap";
import { useLayoutEffect, useRef } from "react";
export function RevealTitle() {
const rootRef = useRef<HTMLHeadingElement>(null);
useLayoutEffect(() => {
const ctx = gsap.context(() => {
gsap.from(".word", {
yPercent: 100,
opacity: 0,
stagger: 0.05,
ease: "power4.out",
});
}, rootRef);
return () => ctx.revert();
}, []);
return <h2 ref={rootRef}><span className="word">Reveal</span></h2>;
}Choose the right hook for the environment
Animation setup needs the browser, so it belongs in a client component. useLayoutEffect is useful when the animation needs to measure or set initial visual state before the browser paints.
For simpler animations that do not need measurement, useEffect can be enough. The important part is that the server-rendered markup still makes sense before the animation runs.
Use timelines for sequences
A timeline is useful when multiple elements need to feel like one designed moment. Instead of scattering delays across separate tweens, the sequence lives in one place.
That makes the animation easier to tune later. You can change the rhythm without hunting through unrelated component code.
Turn effects into tutorials
For component animation tutorials, the article should be more procedural than a normal essay. Start with the effect outcome, name the files, build the static markup, add styling, wire the animation, then list the knobs someone can customize.
That structure works well for effects like magnetic buttons, sticky cursors, image reveals, text masks, scroll triggers, and hover galleries.
RevealTitle
A reusable animated component tutorial that teaches the finished effect, the component structure, and the motion logic in a predictable order.
File map
components/effects/RevealTitle/index.tsxClient component, refs, and GSAP timeline setup.
components/effects/RevealTitle/RevealTitle.module.cssStatic layout, overflow masks, and responsive type rules.
app/example/page.tsxExample usage with real content and surrounding layout.
Steps
Define the static component
Render the HTML and content first so the component is readable without animation.
export function RevealTitle({ children }: { children: string }) {
return <h2 className={styles.title}>{children}</h2>;
}Add the animation boundary
Convert the component to a client component, attach a root ref, and scope GSAP to that root.
const rootRef = useRef<HTMLHeadingElement>(null);
useLayoutEffect(() => {
const ctx = gsap.context(() => {
// Animation lives here.
}, rootRef);
return () => ctx.revert();
}, []);Animate the smallest useful pieces
Target words, lines, images, or layers depending on what the effect needs. Keep selectors local to the component.
Document the knobs
End the tutorial with the values a reader can safely customize: duration, easing, stagger, distance, trigger, colors, and breakpoint behavior.
Options
- Swap the trigger between on-load, on-hover, on-scroll, and in-view.
- Expose duration, stagger, and easing as typed props only when they are genuinely useful.
- Keep reduced-motion behavior explicit for effects that move large areas of the page.
- Document which CSS values are structural and which values are safe to style freely.
GSAP checklist
Render the component normally before adding motion.
Scope selectors with a ref and gsap.context.
Clean up with ctx.revert when the component unmounts.
Write effect tutorials with outcome, file map, build steps, and customization knobs.