AI Website Guides · 2026-10-05 · 5 min read
GSAP ScrollTrigger Examples: 8 Patterns With Code (2026)
GSAP ScrollTrigger links animation to scroll position. Here are eight copy-ready patterns, from pinned sections to scrubbed canvas film, with the code and the gotchas that matter in production.
Written by AmJ, founder of Scrollhaus, and edited by the Scrollhaus editorial team. Sources and methodology are documented in the article.

Key takeaways
Disclosure: ScrollHaus publishes this guide. Technique descriptions come from public documentation of the libraries and browser APIs named, and the live examples are ScrollHaus websites you can scroll yourself.
What is GSAP ScrollTrigger?
ScrollTrigger is a GSAP plugin that starts, pauses, reverses or scrubs animations based on scroll position. Setup is always the same: register the plugin, create a tween or timeline, and give it a scrollTrigger object describing the trigger element and the start and end points.
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
1. Fade and rise on enter
gsap.from('.card', {
y: 40, opacity: 0, duration: 0.8, stagger: 0.12,
scrollTrigger: { trigger: '.cards', start: 'top 80%' }
});
2. Pin a section while it plays
Pinning holds an element in place for a scroll distance so the story can progress.
ScrollTrigger.create({
trigger: '.story', start: 'top top', end: '+=2000', pin: true
});
3. Scrub a timeline with the scrollbar
scrub: true ties progress directly to scroll, so scrolling back rewinds the animation. A number such as scrub: 0.6 adds a little smoothing.
gsap.timeline({
scrollTrigger: { trigger: '.story', start: 'top top', end: '+=3000', scrub: 0.6, pin: true }
})
.to('.title', { scale: 1.4, opacity: 0 })
.from('.panel', { yPercent: 100 }, '<0.3');
4. Horizontal scroll section
const track = document.querySelector('.track');
gsap.to(track, {
x: () => -(track.scrollWidth - innerWidth),
ease: 'none',
scrollTrigger: { trigger: '.h-scroll', pin: true, scrub: 1,
end: () => '+=' + track.scrollWidth, invalidateOnRefresh: true }
});
5. Text reveal line by line
Split headlines into lines (GSAP SplitText or your own wrapper) and stagger them up from a mask. Keep the real heading text in the HTML so search engines can read it.
6. Parallax layers
gsap.utils.toArray('[data-speed]').forEach((el) => {
gsap.to(el, { yPercent: -el.dataset.speed * 20, ease: 'none',
scrollTrigger: { trigger: el, scrub: true } });
});
See parallax website examples for design patterns.
7. Scroll progress bar
gsap.to('.progress', { scaleX: 1, ease: 'none', transformOrigin: 'left',
scrollTrigger: { scrub: true, start: 0, end: 'max' } });
8. Scrub a canvas image sequence
ScrollTrigger can drive a frame counter, and a canvas draws the frame for the current value. This is the same idea as our image sequence canvas tutorial.
const state = { frame: 0 };
gsap.to(state, {
frame: TOTAL - 1, snap: 'frame', ease: 'none',
scrollTrigger: { trigger: '.runway', start: 'top top', end: 'bottom bottom', scrub: 0.5 },
onUpdate: () => draw(state.frame)
});
ScrollTrigger tips for production
- Call
ScrollTrigger.refresh()after images, fonts and dynamic content load. - Use
gsap.matchMedia()to run different animations on mobile and desktop and to honorprefers-reduced-motion. - Pair with Lenis smooth scroll for fluid wheel input.
- Kill triggers on route change in React with
useGSAPor a cleanup function. - Animate transforms and opacity only; avoid animating layout properties.
Frequently confused: GSAP vs Framer Motion
GSAP gives frame-accurate scroll control and timelines in any framework. Framer Motion is declarative and React-native. Our GSAP vs Framer Motion comparison explains when each wins. Browse live scroll-driven builds in the ScrollHaus library.
Explore animated website templates at Scrollhaus →
Need help with a template, account, or project? Email admin@scrollhaus.ai.