Command Palette

Search for a command to run...

GSAP Animations in Production

How I use GSAP on client sites without hurting performance — scroll triggers, page transitions, and knowing when to stop.

Nguyễn Đình Giang

· · 1 min read

Frontend developer in Ha Noi. I write about the Next.js, WordPress, and performance work I actually ship.

Animation is the fastest way to make a site feel premium — or the fastest way to make it feel slow. On corporate sites and agency projects, I use GSAP to add motion that supports the brand, not distracts from it.

My default stack

  • GSAP for timeline-based animations
  • ScrollTrigger for scroll-linked effects
  • Swiper for carousels with parallax slides
  • prefers-reduced-motion checks where motion isn't essential

A simple hero entrance

useEffect(() => {
  const ctx = gsap.context(() => {
    gsap.from(".hero-title", {
      y: 40,
      opacity: 0,
      duration: 0.8,
      ease: "power3.out",
    })
  })
 
  return () => ctx.revert()
}, [])

Always wrap GSAP in gsap.context() and clean up on unmount. Orphaned tweens cause jank when navigating in Next.js.

Rules I follow

  1. Animate transform and opacity — avoid layout-triggering properties
  2. One hero moment per page — not every element needs to fly in
  3. Respect reduced motion — offer a static fallback
  4. Test on mid-range phones — if it stutters on a 3-year-old Android, dial it back
  5. Lazy-init ScrollTrigger — don't register triggers for off-screen sections immediately

Parallax without the lag

On project galleries I use Swiper's parallax module with watchSlidesProgress instead of heavy scroll listeners on every frame. Less main-thread work, smoother swipes.

When not to use GSAP

For simple hover states or toggles, CSS transitions are enough. GSAP earns its place when you need sequenced timelines, scroll choreography, or cross-element coordination — the kind of brand storytelling I used on the luxury travel brand and corporate landing case studies.

Motion should feel intentional — like the site is responding to you, not performing for you.

Official docs I keep open while shipping: GSAP, ScrollTrigger, and Next.js Client Components for where the effect is allowed to run.

River BotAsk me