Advanced GSAP Animations: Creating Stunning Web Experiences
Frontend13 min read

Advanced GSAP Animations: Creating Stunning Web Experiences

Master GSAP for professional web animations. ScrollTrigger, timelines, SVG animations, and performance optimization techniques.

Taha Kocal

Taha Kocal

Full Stack Developer

Nov 5, 2024
#GSAP#Animation#JavaScript#Frontend#UX

GSAP (GreenSock Animation Platform) is the industry-standard JavaScript animation library for building high-performance web animations, from simple tweens to complex scroll-driven experiences. It animates anything JavaScript can touch - CSS properties, SVG, canvas, and WebGL - and powers animations on millions of websites, including many award-winning experiences. Its core API is small: gsap.to, gsap.from, and gsap.fromTo create tweens, timelines sequence them with precise overlap control, and plugins such as ScrollTrigger add scroll-based triggering, scrubbing, and pinning. Because GSAP animates GPU-accelerated transform properties and runs its own optimized ticker, it stays smooth at 60fps where CSS or naive requestAnimationFrame code often stutters. In this guide we cover the fundamentals - tweens, timelines, and easing - then move to ScrollTrigger, React integration with the useGSAP hook, stagger and text effects, SVG animation, and the performance rules that keep everything fast in production.

Getting Started

bash
npm install gsap

Basic Animation

typescript
import gsap from 'gsap';

// Animate to target values
gsap.to('.box', {
  x: 200,
  rotation: 360,
  duration: 2,
  ease: 'power2.out',
});

// Animate from values
gsap.from('.box', {
  opacity: 0,
  y: 100,
  duration: 1,
});

// Animate from/to specific values
gsap.fromTo('.box',
  { opacity: 0, scale: 0.5 },
  { opacity: 1, scale: 1, duration: 1 }
);

How Do GSAP Timelines Work?

Timelines let you sequence multiple animations with precise control over timing and synchronization.

typescript
const tl = gsap.timeline({
  defaults: { duration: 0.5, ease: 'power2.out' },
});

tl.from('.hero-title', { y: 50, opacity: 0 })
  .from('.hero-subtitle', { y: 30, opacity: 0 }, '-=0.3')  // Start 0.3s before previous ends
  .from('.hero-button', { scale: 0, opacity: 0 }, '-=0.2')
  .from('.hero-image', { x: 100, opacity: 0 }, '-=0.4');

// Control methods
tl.play();
tl.pause();
tl.reverse();
tl.seek(1.5);     // Jump to 1.5 seconds
tl.progress(0.5); // Jump to 50%

Nested Timelines

typescript
function createHeaderAnimation() {
  const tl = gsap.timeline();
  tl.from('.logo', { x: -50, opacity: 0 })
    .from('.nav-item', { y: -20, opacity: 0, stagger: 0.1 });
  return tl;
}

function createHeroAnimation() {
  const tl = gsap.timeline();
  tl.from('.hero-content', { y: 50, opacity: 0 })
    .from('.hero-cta', { scale: 0 });
  return tl;
}

// Master timeline combining animations
const master = gsap.timeline();
master
  .add(createHeaderAnimation())
  .add(createHeroAnimation(), '-=0.5');

How Does ScrollTrigger Work?

ScrollTrigger is GSAP's powerful scroll-based animation plugin that enables sophisticated scroll-driven experiences.

typescript
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

Basic Scroll Animation

typescript
gsap.from('.section', {
  scrollTrigger: {
    trigger: '.section',
    start: 'top 80%',   // When top of element hits 80% from top of viewport
    end: 'top 20%',     // When top of element hits 20% from top
    scrub: true,        // Smooth scrubbing, tied to scroll position
    markers: true,      // Debug markers (remove in production)
  },
  y: 100,
  opacity: 0,
});

Pinning Sections

typescript
gsap.to('.pinned-section', {
  scrollTrigger: {
    trigger: '.pinned-section',
    start: 'top top',
    end: '+=1000',  // Pin for 1000px of scrolling
    pin: true,
    scrub: 1,
  },
  x: 500,
});

Horizontal Scroll Effect

tsx
function HorizontalScroll() {
  const containerRef = useRef<HTMLDivElement>(null);

  useLayoutEffect(() => {
    const panels = gsap.utils.toArray('.panel');
    const totalWidth = (panels.length - 1) * window.innerWidth;

    gsap.to(panels, {
      x: -totalWidth,
      ease: 'none',
      scrollTrigger: {
        trigger: containerRef.current,
        pin: true,
        scrub: 1,
        end: () => '+=' + totalWidth,
      },
    });

    return () => ScrollTrigger.killAll();
  }, []);

  return (
    <div ref={containerRef} className="overflow-hidden">
      <div className="flex">
        {[1, 2, 3, 4].map((i) => (
          <div key={i} className="panel w-screen h-screen flex-shrink-0">
            Panel {i}
          </div>
        ))}
      </div>
    </div>
  );
}

How Do You Use GSAP with React?

typescript
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';

function AnimatedComponent() {
  const containerRef = useRef<HTMLDivElement>(null);

  useGSAP(() => {
    gsap.from('.item', {
      y: 50,
      opacity: 0,
      stagger: 0.1,
      duration: 0.8,
    });
  }, { scope: containerRef }); // Scope animations to container

  return (
    <div ref={containerRef}>
      {items.map((item) => (
        <div key={item.id} className="item">{item.name}</div>
      ))}
    </div>
  );
}

Stagger Animations

typescript
// Basic stagger - 0.1s delay between each element
gsap.from('.card', {
  y: 50,
  opacity: 0,
  stagger: 0.1,
});

// Advanced stagger with grid layout
gsap.from('.grid-item', {
  scale: 0,
  opacity: 0,
  stagger: {
    each: 0.1,
    from: 'center',  // Start from center
    grid: [4, 4],    // 4x4 grid
    axis: 'y',
  },
});

// Random stagger
gsap.from('.particle', {
  y: -100,
  opacity: 0,
  stagger: {
    each: 0.05,
    from: 'random',
  },
});

Text Animations

Split Text Animation

tsx
function SplitTextAnimation({ text }: { text: string }) {
  const containerRef = useRef<HTMLDivElement>(null);

  useGSAP(() => {
    const chars = containerRef.current?.querySelectorAll('.char');

    gsap.from(chars, {
      y: 50,
      opacity: 0,
      rotationX: -90,
      stagger: 0.02,
      duration: 0.5,
      ease: 'back.out(1.7)',
    });
  }, { scope: containerRef });

  return (
    <div ref={containerRef}>
      {text.split('').map((char, i) => (
        <span key={i} className="char inline-block">
          {char === ' ' ? '\u00A0' : char}
        </span>
      ))}
    </div>
  );
}

SVG Animations

typescript
// Path drawing animation
gsap.from('.draw-path', {
  drawSVG: '0%',
  duration: 2,
  ease: 'power2.inOut',
});

// SVG morphing
gsap.to('.morph-path', {
  morphSVG: '.target-path',
  duration: 1,
  ease: 'power2.inOut',
});

How Do You Keep GSAP Animations Performant?

Best practices for performant animations:

  • Use transform properties (x, y, rotation, scale) - GPU accelerated
  • Avoid animating layout properties (width, height, left, top)
  • Use will-change CSS property for animated elements
  • Enable force3D for hardware acceleration
  • Kill animations on component unmount in React
typescript
// Good - GPU accelerated
gsap.to('.box', { x: 100, y: 50, rotation: 45, scale: 1.2 });

// Avoid - Triggers layout recalculation
gsap.to('.box', { left: 100, top: 50, width: 200 });

// Force 3D for better performance
gsap.to('.box', {
  x: 100,
  force3D: true, // Uses translate3d
});

// Cleanup in React
useEffect(() => {
  const ctx = gsap.context(() => {
    // All animations here
  }, containerRef);

  return () => ctx.revert(); // Cleanup on unmount
}, []);

Easing Functions

typescript
// Built-in eases
gsap.to('.box', { x: 100, ease: 'power1.out' });
gsap.to('.box', { x: 100, ease: 'power2.inOut' });
gsap.to('.box', { x: 100, ease: 'elastic.out(1, 0.3)' });
gsap.to('.box', { x: 100, ease: 'bounce.out' });
gsap.to('.box', { x: 100, ease: 'back.out(1.7)' });

GSAP is incredibly powerful for creating professional animations. Key takeaways: use timelines for complex sequences, ScrollTrigger enables scroll-based magic, proper cleanup in React is essential, and GPU-accelerated properties ensure best performance.

Practice these techniques to bring your websites to life with stunning, performant animations that enhance user experience without sacrificing performance.

Share this article

Related Articles