Claude
Skills
Sign in
Back

gsap-scrolltrigger

Included with Lifetime
$97 forever

Comprehensive skill for GSAP (GreenSock Animation Platform) and ScrollTrigger plugin. Use this skill when creating web animations, scroll-driven experiences, timelines, tweens, scroll-triggered animations, pinning, scrubbing, parallax effects, or animating DOM elements, SVG, Canvas, WebGL, or Three.js. Triggers on tasks involving GSAP, ScrollTrigger, smooth animations, scroll effects, or animation sequencing.

Generalscriptsassets

What this skill does


# GSAP & ScrollTrigger Development

## Overview

GSAP (GreenSock Animation Platform) is the industry-leading JavaScript animation library for creating high-performance, production-quality animations. ScrollTrigger is GSAP's powerful plugin for scroll-driven animations. Together, they enable everything from simple UI transitions to complex scroll-based storytelling experiences.

## Core Concepts

### The Basics: Tweens

A **tween** is a single animation from point A to point B.

```javascript
// Animate TO a state (from current)
gsap.to(".box", {
  x: 200,
  rotation: 360,
  duration: 1,
  ease: "power2.inOut"
});

// Animate FROM a state (to current)
gsap.from(".box", {
  opacity: 0,
  y: -50,
  duration: 0.8
});

// Animate FROM-TO (define both start and end)
gsap.fromTo(".box",
  { opacity: 0, scale: 0.5 }, // FROM
  { opacity: 1, scale: 1, duration: 1 } // TO
);
```

### Timelines: Sequencing Animations

**Timelines** orchestrate multiple tweens in sequence or overlap.

```javascript
const tl = gsap.timeline();

// Sequential by default
tl.to(".box1", { x: 100, duration: 1 })
  .to(".box2", { y: 100, duration: 1 })
  .to(".box3", { rotation: 360, duration: 1 });

// With labels for organization
tl.addLabel("start")
  .to(".hero", { opacity: 1, duration: 1 })
  .addLabel("reveal")
  .to(".content", { y: 0, duration: 0.8 }, "reveal") // Start at "reveal" label
  .to(".cta", { scale: 1, duration: 0.5 }, "reveal+=0.5"); // 0.5s after "reveal"
```

### Position Parameter (Timeline Timing)

Control when animations start within a timeline:

```javascript
const tl = gsap.timeline();

// Default: One after another
tl.to(".box1", { x: 100 })
  .to(".box2", { x: 100 }); // Starts after box1 finishes

// Start at the same time
tl.to(".box1", { x: 100 })
  .to(".box2", { y: 100 }, 0); // Starts at 0 seconds

// Relative positioning
tl.to(".box1", { x: 100, duration: 2 })
  .to(".box2", { y: 100 }, "-=1"); // Starts 1 second before box1 ends
  .to(".box3", { rotation: 360 }, "+=0.5"); // Starts 0.5s after box2 finishes

// At a specific time
tl.to(".box1", { x: 100 }, 2.5); // Starts at 2.5 seconds
```

## ScrollTrigger Fundamentals

### Basic Scroll Animation

```javascript
gsap.registerPlugin(ScrollTrigger);

gsap.to(".box", {
  x: 500,
  scrollTrigger: {
    trigger: ".box",
    start: "top center", // When top of trigger hits center of viewport
    end: "bottom center",
    markers: true, // Development only - shows start/end positions
    scrub: true, // Links animation to scrollbar
    toggleActions: "play none none reverse" // onEnter onLeave onEnterBack onLeaveBack
  }
});
```

### Start & End Positions

Format: `"[trigger position] [viewport position]"`

```javascript
// Common patterns
start: "top top"      // Trigger top hits viewport top
start: "top center"   // Trigger top hits viewport center (default)
start: "top bottom"   // Trigger top hits viewport bottom
start: "center center" // Trigger center hits viewport center

// With offsets
start: "top top+=100"   // 100px below viewport top
start: "top 80%"        // 80% down the viewport
end: "+=500"            // 500px after start position
end: "bottom top"       // Trigger bottom hits viewport top
```

### Scrubbing (Scroll-Synced Animation)

```javascript
// Boolean: Direct link to scrollbar (immediate)
scrub: true

// Number: Smoothing delay in seconds
scrub: 1  // Takes 1 second to "catch up" to scrollbar
scrub: 0.5 // Faster, tighter feel
```

### Toggle Actions

Control animation at four scroll points:

```javascript
toggleActions: "play pause resume reset"
// onEnter | onLeave | onEnterBack | onLeaveBack

// Actions: play, pause, resume, restart, reset, complete, reverse, none
```

Common patterns:
```javascript
toggleActions: "play none none none"       // Play once on enter
toggleActions: "play none none reverse"    // Play forward, reverse back
toggleActions: "play complete reverse reset" // Full control
toggleActions: "restart pause resume pause"  // Restart on each enter
```

## Common Patterns

### 1. Fade In On Scroll

```javascript
gsap.from(".fade-in", {
  opacity: 0,
  y: 50,
  duration: 1,
  scrollTrigger: {
    trigger: ".fade-in",
    start: "top 80%",
    end: "top 50%",
    scrub: 1,
    once: true // Only animate once
  }
});
```

### 2. Pin Element While Scrolling

```javascript
ScrollTrigger.create({
  trigger: ".panel",
  start: "top top",
  end: "+=500", // Pin for 500px of scrolling
  pin: true,
  pinSpacing: true // Add spacing (default true)
});
```

### 3. Horizontal Scroll Section

```javascript
const sections = gsap.utils.toArray(".panel");

gsap.to(sections, {
  xPercent: -100 * (sections.length - 1),
  ease: "none",
  scrollTrigger: {
    trigger: ".container",
    pin: true,
    scrub: 1,
    end: () => "+=" + document.querySelector(".container").offsetWidth
  }
});
```

### 4. Parallax Effect

```javascript
// Slower movement (background layer)
gsap.to(".bg", {
  y: 200,
  ease: "none",
  scrollTrigger: {
    trigger: ".section",
    start: "top bottom",
    end: "bottom top",
    scrub: true
  }
});

// Faster movement (foreground layer)
gsap.to(".fg", {
  y: -100,
  ease: "none",
  scrollTrigger: {
    trigger: ".section",
    start: "top bottom",
    end: "bottom top",
    scrub: true
  }
});
```

### 5. Scroll-Triggered Timeline

```javascript
const tl = gsap.timeline({
  scrollTrigger: {
    trigger: ".container",
    start: "top top",
    end: "+=500",
    scrub: 1,
    pin: true,
    snap: {
      snapTo: "labels", // Snap to timeline labels
      duration: { min: 0.2, max: 3 },
      delay: 0.2,
      ease: "power1.inOut"
    }
  }
});

tl.addLabel("start")
  .from(".title", { scale: 0.3, rotation: 45, autoAlpha: 0 })
  .addLabel("color")
  .from(".box", { backgroundColor: "#28a92b" })
  .addLabel("spin")
  .to(".box", { rotation: 360 })
  .addLabel("end");
```

### 6. Batch Animations (Multiple Elements)

```javascript
// Loop through multiple elements
gsap.utils.toArray(".box").forEach((box, i) => {
  gsap.from(box, {
    y: 100,
    opacity: 0,
    scrollTrigger: {
      trigger: box,
      start: "top 80%",
      end: "top 50%",
      scrub: 1
    }
  });
});

// Or use ScrollTrigger.batch
ScrollTrigger.batch(".box", {
  onEnter: batch => gsap.to(batch, { opacity: 1, y: 0, stagger: 0.15 }),
  onLeave: batch => gsap.set(batch, { opacity: 0 }),
  start: "top 80%",
  once: true
});
```

### 7. Staggered Animations

```javascript
gsap.from(".item", {
  y: 50,
  opacity: 0,
  duration: 0.8,
  stagger: 0.1, // 0.1s between each item
  scrollTrigger: {
    trigger: ".grid",
    start: "top 80%"
  }
});

// Advanced stagger
gsap.from(".item", {
  scale: 0,
  duration: 1,
  stagger: {
    each: 0.1,
    from: "center", // "start", "center", "end", "edges", or index number
    grid: "auto", // For grid layouts
    ease: "power2.inOut"
  }
});
```

## Integration Patterns

### With Three.js / WebGL

```javascript
import * as THREE from 'three';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

// Animate camera
gsap.to(camera.position, {
  x: 5,
  y: 3,
  z: 10,
  scrollTrigger: {
    trigger: "#section2",
    start: "top top",
    end: "bottom top",
    scrub: 1,
    onUpdate: () => camera.lookAt(scene.position)
  }
});

// Animate mesh rotation
gsap.to(mesh.rotation, {
  y: Math.PI * 2,
  scrollTrigger: {
    trigger: "#section3",
    start: "top bottom",
    end: "bottom top",
    scrub: true
  }
});

// Animate material properties
gsap.to(material, {
  opacity: 0,
  scrollTrigger: {
    trigger: "#section4",
    start: "top center",
    end: "center center",
    scrub: 1
  }
});
```

### With React (useGSAP Hook)

```javascript
import { useRef } from 'react';
import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

function Component() {
  const container = useRef();
  const box = useRef();

  u

Related in General