Skip to content

GSAP ScrollTrigger Advanced — Sophisticated Scroll-Driven Effects

DodaTech Updated 2026-06-28 4 min read

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

What is the difference between scrub: true and scrub: 2?

true links animation to scroll instantly. A number adds inertia in seconds for smoothing.

Can I pin an element and still scroll inside it?

Yes. Use pin: true on the container and allow overflow: auto for internal scrolling.

How do I debug ScrollTrigger issues?

Set ScrollTrigger.config({ limitWarning: false }) and use markers: true to visualize start/end points.

Does ScrollTrigger work with horizontal scroll?

Yes. Set scroller: '.horizontal-container' and use horizontal scroll events.

Can I have nested ScrollTriggers?

Yes. Each section can have its own ScrollTrigger. Ensure parent and child triggers do not conflict.

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.

Flip — GSAP Flip for layout. Morph SVG — SVG morphing.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro