function updateHeaderHeight() {
        // Get the height of #brx-header
        const headerHeight = document.querySelector('#brx-header').offsetHeight;
          
        // Store the height in the CSS custom property --header-height
        document.documentElement.style.setProperty('--brxw-header-height', headerHeight + 'px');
    }

    // Execute the function as soon as the document is ready
    document.addEventListener('DOMContentLoaded', function() {
        updateHeaderHeight();  // Initial update of header height when the document is ready

        // Update the header height on window resize and orientation change
        window.addEventListener('resize', updateHeaderHeight);
        window.addEventListener('orientationchange', updateHeaderHeight);
});

GSAP ScrollTrigger: How to Trigger Scroll Animations (Guide)

To trigger GSAP animations on scroll using ScrollTrigger, load GSAP + the ScrollTrigger plugin, register it with gsap.registerPlugin(ScrollTrigger), then attach a scrollTrigger config (with trigger, start, end, and optionally scrub or pin) to any gsap.to(), gsap.from(), or timeline. ScrollTrigger converts scroll position into animation progress — no scroll-event listeners, no manual math. On WordPress, you enqueue the two scripts and drop the same JS into a Bricks Builder Code element.

Why This Guide Exists

If you’ve searched for how to trigger GSAP animations on scroll using ScrollTrigger, you’ve probably already tried IntersectionObserver or a raw scroll event listener and hit the same wall: jank, re-triggering bugs, and animation math that falls apart the moment a client asks for “one more effect.” ScrollTrigger — GSAP’s scroll plugin — solves this at the library level, and as of the GSAP/Webflow merger, it ships free with the standard gsap package, no membership required.

This is a technical, implementation-first walkthrough. You’ll get the setup, the property table you’ll actually reference later, two full code examples (basic + advanced), a WordPress/Bricks Builder integration path, real example sites, and an FAQ block structured for both human readers and AI answer engines.

What Is GSAP ScrollTrigger?

ScrollTrigger is a plugin bundled with GSAP (GreenSock Animation Platform) that links any tween or timeline to the scroll position of the page (or a scrollable container). Instead of writing window.addEventListener('scroll', ...) and calculating percentages yourself, you describe where an element should start and end reacting to scroll, and ScrollTrigger handles the math, resize recalculation, and cleanup.

Three things make it different from CSS scroll-timeline or vanilla Intersection Observer code:

  • Scrubbing — you can bind animation progress directly to scroll position (scrub: true), so the animation moves backward when the user scrolls up.
  • Pinning — an element can be frozen in the viewport while a longer animation plays out underneath it.
  • A single source of truth — start/end points, markers for debugging, and lifecycle callbacks (onEnter, onLeave, onUpdate) all live in one config object.

GSAP works around countless browser inconsistencies, and it’s used on over 12 million sites, which is part of why ScrollTrigger — rather than a hand-rolled scroll listener — is the default choice for production scroll animation today.

ScrollTrigger vs. Other Scroll-Animation Approaches

Approach Setup effort Scrub / reverse on scroll-up Pinning support Browser consistency Best for
GSAP ScrollTrigger Low (declarative config) Yes, built-in (scrub) Yes, built-in (pin) Normalized across browsers Complex, production scroll storytelling
Native CSS scroll-timeline Low, but limited syntax Yes, but CSS-only easing/logic No native pinning Inconsistent support across browsers Simple fades/reveals, progressive enhancement
Intersection Observer (vanilla JS) Medium–high (manual math) No — you build it yourself No — manual position: fixed hacks Consistent, but you own the edge cases Lightweight “fade in once” effects
scroll event listener High (manual throttling, math) Yes, if you write it No — manual only You own all the quirks Legacy projects, no dependencies allowed

Takeaway: if the brief includes scrubbing, pinning, or a sequence of timed steps, ScrollTrigger removes an entire category of bugs you’d otherwise have to write yourself.

Prerequisites

  • Basic HTML/CSS/JS knowledge
  • A page where you control the <head> or can enqueue scripts (plain HTML, WordPress, or a builder like Bricks)
  • GSAP core + ScrollTrigger loaded (both are now part of the same free gsap package — no separate “Club GreenSock” purchase needed)

Step-by-Step: How to Trigger GSAP Animations on Scroll Using ScrollTrigger

Step 1 — Load and register the plugin

Via CDN (fastest for testing or a Bricks Code element):

<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>
  gsap.registerPlugin(ScrollTrigger);
</script>

Via npm (for a build pipeline — React, Vue, or a custom theme):

npm install gsap
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

Registering the plugin isn’t optional — most bundlers tree-shake unused code, and without registerPlugin(), ScrollTrigger gets silently dropped from the build.

Step 2 — Write your first scroll-triggered animation

gsap.registerPlugin(ScrollTrigger);

gsap.from(".fade-box", {
  opacity: 0,
  y: 60,
  duration: 1,
  ease: "power2.out",
  scrollTrigger: {
    trigger: ".fade-box",
    start: "top 80%",   // animation starts when the top of .fade-box hits 80% down the viewport
    end: "bottom 20%",
    toggleActions: "play none none reverse"
  }
});

This is the core pattern behind almost every “fade/slide in as you scroll” effect you’ve seen on modern landing pages.

Step 3 — The ScrollTrigger properties you’ll actually use

Property What it does Common value
trigger The element whose position in the viewport starts/stops the animation ".fade-box"
start Where the trigger begins reacting, as "[trigger-position] [viewport-position]" "top 80%"
end Where it stops reacting "bottom 20%"
scrub Ties animation progress directly to scroll position (true, or a number for “catch-up” delay) true or 1
pin Freezes the trigger element in place while the animation plays true
toggleActions Four actions for onEnter onLeave onEnterBack onLeaveBack "play none none reverse"
markers Shows visual start/end lines — for local debugging only true
onUpdate Callback fired on every scroll update, receives the ScrollTrigger instance (self) => console.log(self.progress)

Step 4 — Advanced example: pinned section + scrubbed timeline

This is the pattern behind most “pin a section and animate through it” scroll stories:

gsap.registerPlugin(ScrollTrigger);

let tl = gsap.timeline({
  scrollTrigger: {
    trigger: "#story-section",
    start: "top top",
    end: "+=1200",      // pin for 1200px of scroll distance
    scrub: 1,            // 1-second "catch up" for a smoother feel
    pin: true,
    anticipatePin: 1     // reduces the 1-frame flash some browsers show right at pin
  }
});

tl.to("#story-title", { opacity: 0, y: -40 })
  .from("#story-image", { scale: 0.8, opacity: 0 }, "<")
  .to("#story-image", { rotateZ: 6, x: 80 });

Because everything is on one timeline, the three steps play back-to-back as the user scrolls, and reverse cleanly if they scroll back up — no extra code needed.

Step 5 — Debug with markers, then remove them

scrollTrigger: {
  trigger: ".fade-box",
  start: "top 80%",
  markers: true // shows colored start/end lines in dev — delete before shipping
}

Always strip markers: true before pushing to production; it’s a debug-only visual aid.

Using GSAP ScrollTrigger in WordPress with Bricks Builder

Bricks Builder doesn’t ship GSAP by default, so the integration has two parts: load the library, then write the trigger logic in a Code element.

  1. Enqueue GSAP + ScrollTrigger in your child theme’s functions.php (preferred over a page-level <script> tag, since it’s cached and loads consistently across the site):
 
php
function enqueue_gsap_scripts() {
    wp_enqueue_script('gsap-core', 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js', [], null, true);
    wp_enqueue_script('gsap-scrolltrigger', 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js', ['gsap-core'], null, true);
}
add_action('wp_enqueue_scripts', 'enqueue_gsap_scripts');
  1. Add a Bricks Code element (or the Bricks “Custom code” section under a Section/Container) at the bottom of the page and drop your ScrollTrigger logic in a <script> tag, targeting the CSS classes you’ve already set on your Bricks elements:
 
html
<script>
  document.addEventListener('DOMContentLoaded', function () {
    gsap.registerPlugin(ScrollTrigger);

    gsap.from(".brxe-block.reveal-on-scroll", {
      opacity: 0,
      y: 50,
      duration: 0.9,
      ease: "power2.out",
      stagger: 0.15,
      scrollTrigger: {
        trigger: ".brxe-block.reveal-on-scroll",
        start: "top 85%"
      }
    });
  });
</script>
  1. In Bricks, give the elements you want to animate a custom CSS class (e.g. reveal-on-scroll) via the element’s Style panel — this keeps your JS selectors stable even if you rearrange the layout later.

Performance note for Bricks/WordPress specifically: load GSAP core + ScrollTrigger only on pages that use them (Bricks lets you conditionally enqueue per template), and always call ScrollTrigger.refresh() after any Bricks popup, tab, or accordion interaction that changes page height — otherwise your start/end points drift out of sync with the new layout.

Real-World Example Sites and Demos

You don’t need to imagine what this looks like in production — these are good reference points:

  • GSAP’s own Showcase (gsap.com/showcase) — curated, GreenSock-approved scroll and interaction demos.
  • Awwwards’ GSAP tag (awwwards.com/websites/gsap) — award-winning agency and product sites built on GSAP, many using ScrollTrigger for pinned storytelling sections.
  • “Made in Webflow: GSAP” gallery — cloneable, real production examples of scroll-triggered text reveals, marquees, and pinned sections you can inspect in DevTools.
  • CodePen scroll-effect collections (search “GSAP ScrollTrigger” on CodePen) — hundreds of open-source pens showing horizontal scroll, scroll-scrubbed video, and SVG-morph-on-scroll patterns you can fork directly.

Studying two or three of these in DevTools — specifically their scrollTrigger config objects — is often faster than reading documentation, because you see real start/end values used at production scale.

Common Mistakes and Performance Tips

Mistake Why it hurts Fix
Animating top/left/width instead of transform/opacity Forces layout reflow on every scroll tick Animate x, y, scale, opacity — GPU-accelerated
Forgetting gsap.registerPlugin(ScrollTrigger) Plugin gets tree-shaken or silently ignored Always register immediately after import
Leaving markers: true in production Visible debug lines on the live site Remove before deploy, or gate behind an env check
Not calling ScrollTrigger.refresh() after dynamic content loads Start/end points miscalculate against the old page height Call .refresh() after images load, accordions open, or AJAX content inserts
Too many separate ScrollTriggers on one page Each one adds a scroll listener and recalculation cost Group related animations into a single Timeline with one scrollTrigger config
No will-change or reduced-motion handling Accessibility and mobile jank Respect prefers-reduced-motion and test on mid-range Android devices

FAQ

What is ScrollTrigger used for in GSAP? ScrollTrigger links a GSAP tween or timeline to scroll position so animations play, pause, reverse, or scrub based on where an element sits in the viewport — without manual scroll-event math.

Is GSAP ScrollTrigger free to use? Yes. Since GreenSock’s acquisition by Webflow, ScrollTrigger and all former “Club GreenSock” bonus plugins are included free in the standard gsap npm package and CDN build — no license purchase required for standard use.

How do I trigger a GSAP animation only once when scrolling? Set toggleActions: "play none none none" inside your scrollTrigger config, or add once: true if you only ever want it to fire a single time and never reverse.

Can ScrollTrigger animate on scroll up as well as scroll down? Yes — that’s what toggleActions and scrub control. "play none none reverse" plays forward on scroll-down and reverses on scroll-up automatically.

Does ScrollTrigger work with React, Vue, or a page builder like Bricks? Yes. In React/Vue, register the plugin inside a useEffect/onMounted hook and clean it up on unmount. In Bricks Builder or WordPress generally, enqueue the scripts site-wide and target your elements’ custom CSS classes from a Code element, as shown above.

Why isn’t my ScrollTrigger animation firing? The two most common causes: you forgot gsap.registerPlugin(ScrollTrigger), or your trigger selector doesn’t match an element that exists in the DOM at the time the script runs. Wrap your setup in DOMContentLoaded or your framework’s mount hook to rule out timing issues.

What’s the difference between scrub and toggleActions? toggleActions plays a fixed-duration animation once triggered (like a switch). scrub continuously ties the animation’s progress percentage to the scrollbar’s position (like a slider) — the animation moves forward and backward in real time as the user scrolls.

Wrapping Up

Once you understand that ScrollTrigger is really just “scroll position → animation progress,” the property table above is genuinely all you need for 90% of real projects — the rest is creative combination of scrub, pin, and toggleActions. Start with the basic fade-in pattern, get comfortable debugging with markers: true, then move to pinned timelines once single-element animations feel too simple for the brief.

If you’re implementing this inside WordPress with Bricks Builder, enqueue GSAP once at the theme level, keep your trigger logic in one Code element per template, and always re-run ScrollTrigger.refresh() after any layout-shifting interaction.