NexusCS

GSAP

JavaScript
GSAP (GreenSock Animation Platform) is a professional-grade JavaScript animation library for building high-performance animations that work in every major browser.
animation
gsap
greensock
scrolltrigger
tweens

Getting started

Installation

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

CDN:

<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>

Register plugins

import { ScrollTrigger } from "gsap/ScrollTrigger";
import { Flip } from "gsap/Flip";

gsap.registerPlugin(ScrollTrigger, Flip);

Plugins must be registered before use.

First animation

// Animate to values
gsap.to(".box", {
  x: 200,
  rotation: 360,
  duration: 1,
  ease: "power2.out",
});

Tween methods

gsap.to()

gsap.to(".box", { x: 100, duration: 1 });

Animate to the given values.

gsap.from()

gsap.from(".box", { opacity: 0, y: -50, duration: 1 });

Animate from the given values to current state.

gsap.fromTo()

gsap.fromTo(".box", { opacity: 0, x: -100 }, { opacity: 1, x: 0, duration: 1 });

Define both start and end values.

gsap.set()

gsap.set(".box", { x: 100, y: 50, opacity: 0 });

Immediately set properties (no animation, duration: 0).

Special properties

Tween config

Property Description Default
duration Seconds 0.5
delay Delay before start 0
ease Easing function "power1.out"
repeat Times to repeat (-1=loop) 0
repeatDelay Gap between repeats 0
yoyo Reverse on each repeat false
stagger Offset for multiple targets -
paused Start paused false
overwrite true, "auto", false false
immediateRender Render on creation varies

Callbacks

gsap.to(".box", {
  x: 100,
  onStart: () => console.log("started"),
  onUpdate: () => console.log("updating"),
  onComplete: () => console.log("done"),
  onRepeat: () => console.log("repeating"),
  onReverseComplete: () => console.log("reversed"),
});

Each callback has a Params variant: onCompleteParams: [arg1, arg2].

CSS properties

Transform shortcuts

GSAP CSS equivalent
x: 100 translateX(100px)
y: 100 translateY(100px)
xPercent: 50 translateX(50%)
yPercent: 50 translateY(50%)
rotation: 90 rotate(90deg)
scale: 2 scale(2)
scaleX: 0.5 scaleX(0.5)
skewX: 30 skewX(30deg)
transformOrigin: "center" transform-origin
autoAlpha: 0 opacity: 0 + visibility: hidden

autoAlpha toggles visibility automatically — use instead of opacity for hiding elements.

3D transforms

gsap.to(".box", {
  rotationX: 45,
  rotationY: 45,
  z: 100,
  transformPerspective: 500,
  force3D: true,
});
Property Description
rotationX Rotate around X axis
rotationY Rotate around Y axis
z Translate Z (depth)
transformPerspective Per-element perspective
force3D Force GPU acceleration

Timelines

Basic timeline

const tl = gsap.timeline({
  defaults: {
    duration: 1,
    ease: "power2.out",
  },
});

tl.to(".box1", { x: 100 })
  .to(".box2", { y: 100 })
  .to(".box3", { rotation: 180 });

Animations play in sequence. defaults apply to all children.

Position parameter

Value Description
1 At absolute 1s
"+=1" 1s after previous end
"-=1" Overlap by 1s
"<" Start of previous
">" End of previous
"<+=0.5" 0.5s after prev start
"myLabel" At named label
tl.to(".a", { x: 100 })
  .to(".b", { y: 100 }, "-=0.5") // overlap
  .to(".c", { rotation: 90 }, "<"); // same start

Labels & nesting

// Labels
tl.addLabel("midpoint").to(".box", { x: 100 }, "midpoint");

// Add at label
tl.add(otherTimeline, "midpoint");
// Nested timelines
const master = gsap.timeline();
master.add(introTimeline()).add(mainTimeline(), "-=0.5").add(outroTimeline());

Easing

Core eases

Ease Description
"none" Linear (no easing)
"power1" Subtle
"power2" Moderate (default-like)
"power3" Strong
"power4" Extra strong
"back" Overshoot
"bounce" Bouncy
"circ" Circular
"elastic" Springy
"expo" Exponential
"sine" Gentle sinusoidal
"steps(n)" Stepped (n steps)

Usage

// Each ease has .in, .out, .inOut variants
gsap.to(".box", { ease: "power2.out" }); // default
gsap.to(".box", { ease: "power2.in" }); // start slow
gsap.to(".box", { ease: "power2.inOut" }); // both ends

gsap.to(".box", { ease: "elastic.out(1, 0.3)" });
gsap.to(".box", { ease: "back.out(1.7)" });
gsap.to(".box", { ease: "steps(12)" });

Default is "power1.out". Omitting the variant defaults to .out.

Stagger

Simple stagger

gsap.to(".box", {
  x: 100,
  stagger: 0.1, // 0.1s between each
});

Advanced stagger

gsap.to(".box", {
  x: 100,
  stagger: {
    each: 0.1, // time between each
    from: "center", // "start", "end", "center", "edges", "random", or index
    grid: "auto", // auto-detect grid
    axis: "x", // "x" or "y" for grid
    ease: "power2.inOut",
  },
});

Control methods

Playback control

const tween = gsap.to(".box", { x: 100, paused: true });

tween.play(); // play from current
tween.pause(); // pause
tween.resume(); // resume from paused
tween.reverse(); // play backward
tween.restart(); // restart from beginning
tween.seek(0.5); // jump to 0.5s
tween.progress(0.5); // jump to 50%
tween.timeScale(2); // double speed
tween.kill(); // destroy
tween.revert(); // revert to pre-GSAP state

State & promises

tween.isActive(); // currently animating?
tween.progress(); // 0–1 progress
tween.duration(); // total duration
tween.time(); // current time

// Promise-based
tween.then(() => {
  console.log("complete");
});

// Or async/await
await gsap.to(".box", { x: 100 });

ScrollTrigger

Basic usage

import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.to(".box", {
  x: 500,
  scrollTrigger: {
    trigger: ".box",
    start: "top center",
    end: "bottom top",
    scrub: true,
  },
});

Full config

scrollTrigger: {
  trigger: ".element",
  start: "top center",     // [trigger] [scroller]
  end: "bottom top",
  scrub: true,             // true, or seconds for smooth
  pin: true,               // pin trigger element
  pinSpacing: true,
  markers: true,           // debug markers
  toggleActions: "play pause resume reset",
  toggleClass: "active",
  onEnter: () => {},
  onLeave: () => {},
  onEnterBack: () => {},
  onLeaveBack: () => {},
}

Start/end syntax

Format: "[trigger position] [scroller position]"

Value Description
"top center" Trigger top at viewport center
"top 80%" Trigger top at 80% from top
"top top" Trigger top at viewport top
"+=300" 300px after start

toggleActions format: "onEnter onLeave onEnterBack onLeaveBack". Values: play, pause, resume, reverse, restart, reset, complete, none.

Utilities & patterns

Utility methods

gsap.utils.toArray(".box");
gsap.utils.clamp(0, 100, value);
gsap.utils.mapRange(0, 100, 0, 1, 50); // 0.5
gsap.utils.normalize(0, 100, 50); // 0.5
gsap.utils.wrap([0, 1, 2], 4); // 1
gsap.utils.snap(5, 13); // 15
gsap.utils.random(0, 100);
gsap.utils.interpolate(0, 100, 0.5); // 50
gsap.utils.shuffle([1, 2, 3]);
gsap.utils.pipe(fn1, fn2, fn3);
gsap.utils.selector(scope);

Function-based values

gsap.to(".box", {
  // Per-element values
  x: (i, target, targets) => i * 50,
  rotation: (i) => i * 90,
});

// Random values
gsap.to(".box", { x: "random(-100, 100)" });
gsap.to(".box", { x: "random(-100, 100, 10)" }); // snapped

// Relative values
gsap.to(".box", { x: "+=20" }); // add 20
gsap.to(".box", { x: "-=20" }); // subtract 20

Context & matchMedia

// Context for cleanup (React, etc.)
const ctx = gsap.context(() => {
  gsap.to(".box", { x: 100 });
  // all animations auto-cleaned
}, containerRef);

ctx.revert(); // cleanup all
// Responsive animations
const mm = gsap.matchMedia();
mm.add("(min-width: 768px)", () => {
  gsap.to(".box", { x: 200 });
  return () => {}; // cleanup
});
mm.add("(max-width: 767px)", () => {
  gsap.to(".box", { x: 50 });
});

quickTo & quickSetter

// Optimized for rapid updates (mousemove, etc.)
const xTo = gsap.quickTo(".box", "x", {
  duration: 0.4,
  ease: "power3",
});
window.addEventListener("mousemove", (e) => xTo(e.clientX));

// Even faster (no tween overhead)
const setX = gsap.quickSetter(".box", "x", "px");
setX(100);

Reusable effects

gsap.registerEffect({
  name: "fadeIn",
  effect: (targets, config) =>
    gsap.from(targets, {
      opacity: 0,
      y: config.y,
      duration: config.duration,
    }),
  defaults: { y: -20, duration: 0.5 },
  extendTimeline: true,
});

// Use it
gsap.effects.fadeIn(".box");
tl.fadeIn(".box", { y: -30 });

Plugins

Free plugins

Plugin Description
ScrollTrigger Scroll-based animations
Draggable Drag and drop
Flip Layout transition animations
Observer Multi-event listener
ScrollToPlugin Animate scroll position
TextPlugin Animate text content
MotionPathPlugin Animate along SVG paths

Premium plugins (Club GSAP)

Plugin Description
DrawSVGPlugin Animate SVG strokes
MorphSVGPlugin Morph between SVG shapes
SplitText Split text for animation
ScrambleTextPlugin Scramble text effect
InertiaPlugin Momentum-based motion
GSDevTools Visual debugging UI

Premium plugins are free on CodePen and Stackblitz.

React integration

useGSAP hook

npm install @gsap/react
import { useRef } from "react";
import { useGSAP } from "@gsap/react";

function MyComponent() {
  const container = useRef();

  useGSAP(
    () => {
      gsap.to(".box", { x: 100 });
    },
    { scope: container },
  );

  return (
    <div ref={container}>
      <div className="box" />
    </div>
  );
}

With dependencies & cleanup

useGSAP(
  () => {
    gsap.to(".box", {
      x: isActive ? 200 : 0,
      rotation: isActive ? 360 : 0,
    });
  },
  { scope: container, dependencies: [isActive] },
);

useGSAP handles cleanup automatically — no manual revert() needed.

Also see