Plugins

Observer

Observer is a GSAP plugin that normalizes wheel, touch, and pointer input into one set of direction and velocity callbacks, so you can react to a gesture without binding it to scroll position the way ScrollTrigger does. It's how you build swipe decks, scroll-jacked section steppers, and direction-aware UI on a single event model that behaves the same on a trackpad, a mouse wheel, and a phone.

Updated June 30, 2026

Mechanics

How Observer works

You call Observer.create() with a target element and a set of direction callbacks. Observer listens to the raw input events on that target, figures out which way the user moved, and fires onUp / onDown / onLeft / onRight once the movement passes the tolerance threshold. It does not move anything itself. You decide what each callback runs.

script.js

The callback receives the Observer instance, so you can read self.deltaX / self.deltaY (how far this move went), self.velocityX / self.velocityY (how fast), and self.isDragging. That velocity signal is the part native event handlers make you compute by hand.

type controls what it listens to

type defaults to "wheel,touch,pointer". Drop wheel if you only want touch and drag gestures, or set type: "touch,pointer" for a swipe-only carousel that ignores the scroll wheel. Set preventDefault: true only when you're fully taking over the input, since it stops the page from scrolling normally.
When

Use it for

  • Full-page section steppers where one wheel notch or swipe advances to the next panel
  • Swipe-driven carousels and card decks that need to feel the same on touch and trackpad
  • Detecting scroll direction (up vs down) to hide or show a header, without caring about exact scroll position
  • Custom drag interactions where you want deltaX / velocityX but not the full weight of Draggable
  • Gesture handling on a nested scroll container or an element that isn't the window
Alternatives

Use something else when

  • You need to tie animation progress to actual scroll position (parallax, scrubbed reveals, pinning), use ScrollTrigger with scrub
  • You're dragging an element around the screen with bounds and momentum, use Draggable plus InertiaPlugin
  • You only need a single touch start/end and no velocity or normalization, native pointer events are lighter
  • You want momentum scrolling of the page itself, that's ScrollSmoother or Lenis, not Observer
In production

Where direction signals show up in Annnimate components

Both of these solve the exact problem Observer is built for, reading the direction of a gesture and reacting to it. They reach it through different inputs, but Observer is the standalone plugin you'd grab to rebuild the direction signal from scratch or move it onto a non-window scroller.

  • Hide Header hides on scroll-down and shows on scroll-up. It currently reads self.direction off a ScrollTrigger, which is the same up/down signal Observer's onUp / onDown give you. Observer is the lighter route when you want that signal without binding to scroll position, for example inside an app shell that scrolls its own panel instead of the window
  • Mega Menu plays a direction-aware reveal, animating each panel in from whichever side the cursor came from. That left/right intent is the pointer equivalent of Observer's onLeft / onRight callbacks

Free, and worth gating on reduced motion

Observer ships with the free GSAP core (every former Club plugin became free with GSAP 3.13, fully live April 30 2025, per webflow.com). Since Observer is often the trigger for big motion like full-page section jumps, gate the animation it fires behind a reduced-motion check, prefers-reduced-motion adoption passed 50% of mobile sites in 2024, up from 34% in 2022 (HTTP Archive Web Almanac 2024). Use gsap.matchMedia() for that branch.
Used in components

See it running in production

FAQ

Common questions

What's the difference between Observer and ScrollTrigger?
ScrollTrigger ties animation to scroll position, you give it a start and end on the page and it plays, scrubs, or pins within that range. Observer ignores position entirely. It just tells you the user moved up, down, left, or right with some velocity, and lets you decide what happens. Use ScrollTrigger when 'how far down the page am I' matters, use Observer when 'which way did they swipe' matters. ScrollTrigger actually uses Observer internally for its input normalization.
How do I detect swipe direction with GSAP Observer?
Set type: "touch,pointer" and add onLeft / onRight (or onUp / onDown) callbacks to Observer.create(). Each fires once the movement passes tolerance pixels in that direction. Read self.deltaX and self.velocityX inside the callback if you want the throw distance and speed, for example to decide whether a swipe was forceful enough to advance two cards instead of one.
Does Observer work on both touch and mouse wheel?
Yes, that's the point of it. The type option defaults to "wheel,touch,pointer", so the same onUp / onDown callbacks fire whether the user scrolled a wheel, swiped a touchscreen, or dragged with a pointer. You write the gesture logic once and it behaves consistently across devices instead of wiring up wheel, touchmove, and pointermove separately.
How do I stop or clean up an Observer?
Observer.create() returns the instance. Call observer.kill() to remove its listeners, and observer.disable() / observer.enable() to pause and resume without tearing it down. In React, kill it inside the useGSAP cleanup return so it doesn't leak across re-renders or unmounts.
Is the Observer plugin paid or Club-only?
It's free. Observer ships in the free GSAP core and has since before the licensing change, and as of GSAP 3.13 every plugin, including the former Club GSAP ones, is free for commercial use. You just import { Observer } from "gsap/Observer" and register it.