The Beginner's Guide to GSAP ScrollTrigger (Part 2): Pinning and Scrubbing Like a Pro

Welcome back to our series on mastering GSAP ScrollTrigger!

In Part 1 of this series, we got our feet wet by making elements magically appear on scroll. You’ve mastered the art of the reveal! Now, it's time to unlock the jaw-dropping features that create cinematic, story-driven web experiences.

Imagine a section that sticks to the screen while you scroll, with an animation that plays forward and backward as you move your scrollbar. That's exactly what we're building today.

The Goal: A "Sticky Progress" Animation

We're going to build a section that pins itself to the viewport. As we scroll "through" it, a progress bar at the top of the page will fill up, perfectly in sync with our scroll position.


Step 1: The HTML Layout

We'll use a similar layout, but with a progress bar and a section designed to be pinned.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ScrollTrigger Part 2: Pin & Scrub</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>

    <div class="progress-bar"></div>

    <section class="section-intro">
        <h1>Let's Do Something Amazing</h1>
        <p>Scroll down...</p>
    </section>

    <section class="section-pinned">
        <h2>This Section is Pinned!</h2>
        <p>As you scroll, watch the progress bar above. It's directly tied to your scrollbar. This is the power of 'scrub'!</p>
    </section>

    <section class="section-outro">
        <h1>And... we're back to normal scrolling.</h1>
    </section>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>

    <script src="app.js"></script>
</body>
</html>

Step 2: Styling for the Pin

The CSS is key here. We need to give our pinned section a height greater than the viewport to create scrollable space while it's pinned.

Create your style.css file:

body {
    font-family: 'Montserrat', sans-serif;
    margin: 0;
    background-color: #1c1c1c;
    color: #e0e0e0;
}

.progress-bar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 10px;
    background: linear-gradient(to right, #8e44ad, #3498db);
    transform-origin: left;
    transform: scaleX(0); /* Start scaled to 0 */
    z-index: 100;
}

section {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    min-height: 100vh;
}

.section-pinned {
    /* THIS IS IMPORTANT! The height determines how long we scroll while it's pinned. */
    height: 200vh; 
    background-color: #2c3e50;
}

Step 3: The Insightful JavaScript

Here's where we orchestrate our masterpiece. We'll create two separate ScrollTriggers—one for the progress bar animation and one to handle the pinning.

Fire up your app.js file:

// Register the plugin
gsap.registerPlugin(ScrollTrigger);

// --- 1. THE PROGRESS BAR ---
gsap.to(".progress-bar", {
    scaleX: 1,
    ease: "none",
    scrollTrigger: {
        trigger: ".section-pinned",
        start: "top top",
        end: "bottom bottom",
        scrub: 1, 
    }
});

// --- 2. THE PINNING ---
ScrollTrigger.create({
    trigger: ".section-pinned",
    start: "top top",
    end: "bottom bottom",
    pin: true,
    pinSpacing: false,
    markers: true
});

Why This is a Game-Changer

Let's break down these new superpowers:

  • pin: true: This is the thumbtack! It locks the trigger element in place while you scroll over its defined length. It's perfect for holding a product in view while you list its features.

  • scrub: 1: This is the most exciting part. Instead of just playing an animation, scrub links the animation's progress directly to the scrollbar's position. It's like being a DJ with an animation track! The 1 adds a smooth, one-second "catch up" time.

By separating these two, you've learned a core concept of advanced animation: decoupling. The progress bar's animation is driven by the scroll distance of the pinned section, but they are two distinct pieces of logic. This is how you build incredibly complex and layered web pages.

0
Subscribe to my newsletter

Read articles from Dharma Yudistira directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dharma Yudistira
Dharma Yudistira

I'm a passionate Product Engineer specializing in building high-performance, scalable web and mobile applications . Explore my projects and let's build something amazing together.