GSAP ScrollTrigger Advanced — Sophisticated Scroll-Driven Effects
In this tutorial, you will learn about GSAP ScrollTrigger Advanced. We cover key concepts, practical examples, and best practices to help you master this topic.
GSAP ScrollTrigger advanced techniques enable sophisticated scroll-driven animations with pinning, scrubbing, multi-panel layouts, parallax effects, and responsive breakpoints.
What You'll Learn
By the end of this guide, you will create scrubbed animations tied to scroll progress, build pinned sections with multiple panel reveals, implement parallax with different scroll speeds, use batch animations for grids, and configure responsive ScrollTrigger breakpoints.
Scrub with Inertia
gsap.to('.progress-bar', {
scaleX: 1,
transformOrigin: 'left center',
scrollTrigger: {
trigger: '.content',
start: 'top top',
end: 'bottom top',
scrub: 2
}
});
Multi-Panel Pin
var panels = document.querySelectorAll('.panel');
panels.forEach(function(panel, i) {
ScrollTrigger.create({
trigger: panel,
start: 'top top',
pin: panels[i - 1] || true,
pinSpacing: false
});
});
Parallax with Batch
gsap.utils.toArray('.parallax-item').forEach(function(item) {
var speed = item.dataset.speed || 0.5;
gsap.to(item, {
y: 100 * (1 - speed),
ease: 'none',
scrollTrigger: {
trigger: item,
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
});
Responsive ScrollTrigger
ScrollTrigger.create({
trigger: '.section',
start: 'top center',
end: 'bottom center',
toggleClass: 'active',
// Disable on mobile
condition: window.innerWidth > 768,
onRefresh: function(self) {
self.enable();
}
});
Common Mistakes
1. scrub Value Too High
Scrub value of 2+ adds 2 seconds of inertia, making the animation feel unresponsive. Use 0.5-1 for most cases.
2. Pin Spacing Issues
When pinning multiple elements, pinSpacing must be set correctly. false for overlapping pins, true for spacing.
3. Not Calling ScrollTrigger.refresh()
After DOM changes, call ScrollTrigger.refresh() to recalculate positions. Forgetting this causes misalignment.
4. Batch Animations on Dynamic Content
When content loads asynchronously, run ScrollTrigger creation after the DOM is ready.
5. Ignoring ScrollTrigger.matchMedia()
Use ScrollTrigger.matchMedia() for responsive behavior instead of manual window resize listeners.
Practice Questions
Q1: What does scrub do? A: It links the animation progress to scroll position. A value of 1 adds 1 second of inertia smoothing.
Q2: How do you pin multiple panels? A: Create a ScrollTrigger for each panel with pin: true. Manage pinSpacing to avoid gaps.
Q3: How do you create parallax effects? A: Animate y (or scale) with scrub: true at different speeds per element.
Q4: How do you refresh ScrollTrigger after DOM changes? A: Call ScrollTrigger.refresh() to recalculate all trigger positions.
Q5: How do you disable ScrollTrigger on mobile? A: Use ScrollTrigger.matchMedia() or set a condition check in the ScrollTrigger config.
Challenge: Build a landing page with a hero parallax, a pinned section showing 4 sequentially revealed panels, and a scrubbed progress bar that fills from 0 to 100% as the user scrolls.
FAQ
Try It Yourself
Build a scrubbed progress bar and parallax section.
<!DOCTYPE html>
<html>
<head>
<title>ScrollTrigger Advanced Demo</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12/ScrollTrigger.min.js"></script>
<script>gsap.registerPlugin(ScrollTrigger);</script>
<style>
body { margin: 0; font-family: sans-serif; }
.section { min-height: 100vh; display: flex; align-items: center; justify-content: center; font-size: 2rem; }
.s1 { background: #1a1a2e; color: white; }
.s2 { background: #4ecdc4; color: #1a1a2e; }
.s3 { background: #ff6b35; color: white; }
.s4 { background: #2a9d8f; color: white; }
.progress { position: fixed; top: 0; left: 0; width: 100%; height: 4px; background: #eee; z-index: 100; }
.progress-fill { height: 100%; width: 0; background: #ff6b35; transform-origin: left; }
.parallax-box { width: 200px; height: 200px; background: rgba(255,255,255,0.15); border-radius: 16px; display: flex; align-items: center; justify-content: center; }
</style>
</head>
<body>
<div class="progress"><div class="progress-fill" id="progress-fill"></div></div>
<section class="section s1">Scroll Down</section>
<section class="section s2">
<div class="parallax-box" id="para1" data-speed="0.3">Slow</div>
</section>
<section class="section s3">
<div class="parallax-box" id="para2" data-speed="0.7">Fast</div>
</section>
<section class="section s4">The End</section>
<script>
gsap.to('#progress-fill', {
scaleX: 1,
ease: 'none',
scrollTrigger: { trigger: 'body', start: 'top top', end: 'bottom bottom', scrub: 0.5 }
});
document.querySelectorAll('[data-speed]').forEach(function(el) {
var speed = parseFloat(el.dataset.speed);
gsap.to(el, {
y: 200 * (1 - speed),
ease: 'none',
scrollTrigger: { trigger: el.closest('section'), start: 'top bottom', end: 'bottom top', scrub: true }
});
});
</script>
</body>
</html>
What's Next
Use Flip plugin for layout animations.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro