← Back to Lesson

🎯 GSAP ScrollTrigger

Scroll to Explore

Scroll-driven animations made simple

📖 What is ScrollTrigger?

ScrollTrigger is GSAP's plugin that synchronizes animations with scroll position. It's more powerful and reliable than CSS scroll-driven animations, works across all browsers, and provides precise control over when and how animations trigger.

⚡ Key Features

🎯 When to Use ScrollTrigger

Perfect for reveal animations, parallax effects, scroll-driven progress indicators, animated infographics, interactive storytelling, and any animation that should respond to scroll position. It replaces unreliable scroll event listeners with a battle-tested, performant solution.

Parallax Effect

Background moves slower than viewport

This section is pinned while you scroll. Watch the text change!
I change color on scroll!

📝 Code Examples

1. Basic Fade In

gsap.to('.content-card', {
  opacity: 1,
  y: 0,
  duration: 1,
  scrollTrigger: {
    trigger: '.content-card',
    start: 'top 80%',      // When top hits 80% down viewport
    end: 'top 20%',        // When top hits 20% down viewport
    toggleActions: 'play none none reverse',
    markers: true          // Show debug markers
  }
});

2. Scrub Animation

gsap.to('.element', {
  x: 500,
  rotation: 360,
  scrollTrigger: {
    trigger: '.section',
    start: 'top top',
    end: 'bottom top',
    scrub: true,           // Sync with scroll position
    pin: true              // Pin the element
  }
});

3. Timeline with ScrollTrigger

const tl = gsap.timeline({
  scrollTrigger: {
    trigger: '.section',
    start: 'top center',
    end: 'bottom center',
    scrub: 1,              // 1 second lag for smooth feel
  }
});

tl.to('.box1', { x: 100, duration: 1 })
  .to('.box2', { y: 100, duration: 1 }, '-=0.5')
  .to('.box3', { rotation: 360, duration: 1 });

4. Toggle Class

ScrollTrigger.create({
  trigger: '.element',
  start: 'top center',
  end: 'bottom center',
  toggleClass: { targets: '.element', className: 'is-active' },
  onEnter: () => console.log('Entered!'),
  onLeave: () => console.log('Left!')
});