Gsap Scrolltrigger

Bbeierle12/Skill-MCP-Claude/skills/gsap-scrolltrigger

by Bbeierle12c35d6c509b8f0331697f19ef45b651f274deba60No license8 starsListed Oct 9, 2026Updated Oct 9, 2026Repository updated today

Scroll-based animations using GSAP ScrollTrigger plugin including pinning, scrubbing, snap points, and parallax effects. Use when creating scroll-driven animations, sticky sections, progress indicators, or parallax scrolling experiences.

AI-generated overview

Reference guide for building scroll-driven animations with the GSAP ScrollTrigger plugin.

What it does
This skill is an instructional reference for the GSAP ScrollTrigger plugin. It documents core concepts such as trigger start and end positions, scrubbing, pinning, toggle actions, snap points, callbacks, parallax layers, horizontal scrolling, batch animations and development markers, with JavaScript code examples for each. It also covers common patterns like reveal-on-scroll, progress indicators and sticky headers, plus performance tips such as matchMedia and refresh.
When to use it
Use it when creating scroll-driven animations, sticky or pinned sections, scroll progress indicators, snap points or parallax scrolling experiences in a web project. It is also useful as a lookup for ScrollTrigger configuration options and callback behavior.
Requirements
Requires the GSAP package installed via npm (npm install gsap) and a JavaScript project that imports gsap and the ScrollTrigger plugin. Ships no scripts; it is instructions and code examples only.

GSAP ScrollTrigger

Scroll-driven animations and interactions.

Quick Start

bash
npm install gsap
javascript
import gsap from 'gsap';import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
gsap.to('.box', {  x: 500,  scrollTrigger: {    trigger: '.box',    start: 'top center',    end: 'bottom center',    scrub: true  }});

Core Concepts

Basic ScrollTrigger

javascript
gsap.to('.element', {  x: 200,  scrollTrigger: {    trigger: '.element',  // Element that triggers the animation    start: 'top center',  // When trigger hits viewport center    end: 'bottom center', // When trigger leaves viewport center    toggleActions: 'play pause resume reset'  }});

Start/End Positions

javascript
// Format: "trigger-position viewport-position"start: 'top center'      // Trigger's top hits viewport centerstart: 'top 80%'         // Trigger's top hits 80% down viewportstart: 'center center'   // Trigger's center hits viewport centerstart: 'bottom top'      // Trigger's bottom hits viewport topstart: 'top top+=100'    // Trigger's top hits 100px below viewport top

Position Reference

ValueDescription
topTop edge
centerCenter
bottomBottom edge
80%80% from top
+=100Plus 100 pixels
-=50Minus 50 pixels

Scrub Animations

Basic Scrub

javascript
// Animation progress tied to scroll positiongsap.to('.progress-bar', {  scaleX: 1,  scrollTrigger: {    trigger: '.content',    start: 'top top',    end: 'bottom bottom',    scrub: true  // Directly linked to scroll  }});

Smooth Scrub

javascript
gsap.to('.element', {  x: 500,  scrollTrigger: {    trigger: '.section',    scrub: 1,    // 1 second smoothing    // scrub: 0.5  // 0.5 second smoothing    // scrub: 2    // 2 second smoothing (laggy feel)  }});

Scrub with Timeline

javascript
const tl = gsap.timeline({  scrollTrigger: {    trigger: '.container',    start: 'top top',    end: '+=3000',  // Scroll distance    scrub: 1,    pin: true  }});
tl.to('.step1', { opacity: 1 })  .to('.step2', { opacity: 1 })  .to('.step3', { opacity: 1 });

Pinning

Basic Pin

javascript
ScrollTrigger.create({  trigger: '.panel',  start: 'top top',  end: '+=500',      // Pin for 500px of scroll  pin: true});

Pin with Animation

javascript
gsap.to('.content', {  x: '-200%',  ease: 'none',  scrollTrigger: {    trigger: '.horizontal-section',    start: 'top top',    end: () => '+=' + document.querySelector('.horizontal-section').offsetWidth,    pin: true,    scrub: 1  }});

Pin Spacing

javascript
ScrollTrigger.create({  trigger: '.section',  pin: true,  pinSpacing: true,   // Default: adds space for pinned duration  // pinSpacing: false  // No extra space (content overlaps)  // pinSpacing: '500px' // Custom spacing});

Toggle Actions

Action Syntax

javascript
// Format: "onEnter onLeave onEnterBack onLeaveBack"toggleActions: 'play pause resume reset'
// Common combinations:toggleActions: 'play none none none'     // Play oncetoggleActions: 'play reverse play reverse' // Toggle directiontoggleActions: 'restart none none none'  // Restart each timetoggleActions: 'play complete reverse reset'

Action Values

ActionEffect
playPlay forward
pausePause
resumeResume from paused
reversePlay backward
restartRestart from beginning
resetReset to start (no animation)
completeJump to end
noneDo nothing

Snap Points

Basic Snap

javascript
ScrollTrigger.create({  trigger: '.sections',  start: 'top top',  end: 'bottom bottom',  snap: 1 / 4  // Snap to quarters});

Snap to Labels

javascript
const tl = gsap.timeline({  scrollTrigger: {    trigger: '.container',    scrub: 1,    snap: {      snapTo: 'labels',      duration: 0.5,      ease: 'power2.inOut'    }  }});
tl.addLabel('intro')  .to('.a', { opacity: 1 })  .addLabel('middle')  .to('.b', { opacity: 1 })  .addLabel('end');

Snap Configuration

javascript
snap: {  snapTo: [0, 0.25, 0.5, 0.75, 1],  // Snap to specific points  duration: { min: 0.2, max: 0.6 }, // Snap duration range  delay: 0,                          // Delay before snap  ease: 'power1.inOut',             // Snap easing  directional: true                  // Snap in scroll direction}

Callbacks

ScrollTrigger Callbacks

javascript
ScrollTrigger.create({  trigger: '.section',  onEnter: () => console.log('Entered'),  onLeave: () => console.log('Left'),  onEnterBack: () => console.log('Entered from bottom'),  onLeaveBack: () => console.log('Left going up'),  onUpdate: (self) => console.log('Progress:', self.progress),  onToggle: (self) => console.log('Active:', self.isActive),  onRefresh: () => console.log('Refreshed')});

Progress-Based Updates

javascript
ScrollTrigger.create({  trigger: '.section',  start: 'top bottom',  end: 'bottom top',  onUpdate: (self) => {    // self.progress: 0 to 1    // self.direction: 1 (down) or -1 (up)    // self.velocity: scroll speed    updateElement(self.progress);  }});

Parallax Effects

Basic Parallax

javascript
// Background moves slower than scrollgsap.to('.background', {  yPercent: -50,  ease: 'none',  scrollTrigger: {    trigger: '.section',    scrub: true  }});
// Foreground moves fastergsap.to('.foreground', {  yPercent: 50,  ease: 'none',  scrollTrigger: {    trigger: '.section',    scrub: true  }});

Multi-Layer Parallax

javascript
const layers = [  { selector: '.layer-1', speed: -20 },  { selector: '.layer-2', speed: -40 },  { selector: '.layer-3', speed: -60 },  { selector: '.layer-4', speed: -80 }];
layers.forEach(layer => {  gsap.to(layer.selector, {    yPercent: layer.speed,    ease: 'none',    scrollTrigger: {      trigger: '.parallax-section',      start: 'top bottom',      end: 'bottom top',      scrub: true    }  });});

Horizontal Scrolling

Horizontal Section

javascript
const sections = gsap.utils.toArray('.panel');
gsap.to(sections, {  xPercent: -100 * (sections.length - 1),  ease: 'none',  scrollTrigger: {    trigger: '.horizontal-container',    pin: true,    scrub: 1,    snap: 1 / (sections.length - 1),    end: () => '+=' + document.querySelector('.horizontal-container').offsetWidth  }});

Markers (Development)

javascript
ScrollTrigger.create({  trigger: '.section',  start: 'top center',  end: 'bottom center',  markers: true,  // Show visual markers  // markers: { startColor: 'green', endColor: 'red', fontSize: '12px' }});

Batch Animations

Stagger on Scroll

javascript
ScrollTrigger.batch('.card', {  onEnter: (elements) => {    gsap.from(elements, {      opacity: 0,      y: 50,      stagger: 0.1,      duration: 0.5    });  },  start: 'top 85%'});

Batch Configuration

javascript
ScrollTrigger.batch('.item', {  interval: 0.1,  // Time between batches  batchMax: 3,    // Max items per batch  onEnter: batch => gsap.to(batch, { opacity: 1, y: 0, stagger: 0.1 }),  onLeave: batch => gsap.to(batch, { opacity: 0, y: 20 }),  onEnterBack: batch => gsap.to(batch, { opacity: 1, y: 0 }),  onLeaveBack: batch => gsap.to(batch, { opacity: 0, y: -20 })});

Common Patterns

Reveal on Scroll

javascript
gsap.utils.toArray('.reveal').forEach(elem => {  gsap.from(elem, {    opacity: 0,    y: 50,    duration: 0.8,    scrollTrigger: {      trigger: elem,      start: 'top 80%',      toggleActions: 'play none none none'    }  });});

Progress Indicator

javascript
gsap.to('.progress-bar', {  scaleX: 1,  transformOrigin: 'left center',  ease: 'none',  scrollTrigger: {    trigger: 'body',    start: 'top top',    end: 'bottom bottom',    scrub: 0.3  }});

Sticky Header Transform

javascript
ScrollTrigger.create({  start: 'top -80',  onUpdate: (self) => {    if (self.direction === 1) {      gsap.to('.header', { y: -80, duration: 0.3 });    } else {      gsap.to('.header', { y: 0, duration: 0.3 });    }  }});

Temporal Collapse Patterns

Countdown Scroll Reveal

javascript
// Reveal countdown sections as user scrollsconst sections = ['days', 'hours', 'minutes', 'seconds'];
sections.forEach((section, i) => {  gsap.from(`.countdown-${section}`, {    opacity: 0,    scale: 0.8,    y: 50,    duration: 0.8,    ease: 'power3.out',    scrollTrigger: {      trigger: `.countdown-${section}`,      start: 'top 80%',      toggleActions: 'play none none none'    }  });});

Scroll-Based Time Dilation Effect

javascript
gsap.timeline({  scrollTrigger: {    trigger: '.time-section',    start: 'top center',    end: 'bottom center',    scrub: 1  }}).to('.time-digit', {  textShadow: '0 0 50px #00F5FF, 0 0 100px #00F5FF',  scale: 1.1}).to('.particles', {  opacity: 1,  filter: 'blur(0px)'}, '<');

Performance Tips

javascript
// Disable on mobile if neededScrollTrigger.matchMedia({  '(min-width: 768px)': function() {    // Desktop animations  },  '(max-width: 767px)': function() {    // Simpler mobile animations  }});
// Refresh on resizeScrollTrigger.refresh();
// Kill all ScrollTriggersScrollTrigger.killAll();
// Kill specific triggerconst st = ScrollTrigger.create({ ... });st.kill();

Reference

  • See gsap-fundamentals for animation basics
  • See gsap-sequencing for timeline composition
  • See gsap-react for React integration with ScrollTrigger

Source and attribution

Source:Bbeierle12/Skill-MCP-Claudeinskills/gsap-scrolltriggerat commitc35d6c5

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal