GSAP Cheatsheet

SVG and Utilities

Use this GSAP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

SVG Animation Basics

Transform on SVG elements

SVG elements don't support CSS transforms the same way HTML elements do in older browsers. GSAP normalizes this automatically.

// GSAP handles SVG transforms cross-browser
gsap.to("#myRect", { x: 100, y: 50, rotation: 45, scale: 1.5 });

// transformOrigin relative to the SVG viewport
gsap.set("#myRect", { transformOrigin: "center center" });

// svgOrigin: use SVG coordinate space (not CSS %)
gsap.to("#gear", {
  rotation: 360,
  svgOrigin: "250 250", // "x y" in SVG user units
  repeat: -1,
  ease: "none",
  duration: 3,
});

Animating SVG attributes

// attr:{} animates SVG presentation attributes
gsap.to("circle", { attr: { cx: 300, cy: 200, r: 80 }, duration: 1 });
gsap.to("rect",   { attr: { width: 200, fill: "#ff4444" }, duration: 0.5 });
gsap.to("line",   { attr: { x2: 400, y2: 300 }, duration: 0.8 });
gsap.to("ellipse",{ attr: { rx: 100, ry: 50 }, duration: 0.6 });

// Stroke properties
gsap.to("path", {
  attr: { stroke: "#d4af37", "stroke-width": 4 },
  duration: 0.3,
});

Draw-on effect (stroke-dashoffset)

// Measure path length first
const path = document.querySelector("path");
const length = path.getTotalLength(); // e.g. 842

// Set up: dashes = full length, offset = full length (invisible)
gsap.set(path, {
  attr: { "stroke-dasharray": length, "stroke-dashoffset": length },
});

// Animate offset to 0 = draws the line
gsap.to(path, {
  attr: { "stroke-dashoffset": 0 },
  duration: 2,
  ease: "power2.inOut",
});

DrawSVGPlugin

Free since GSAP 3.13. Much easier than manual dashoffset. Animates how much of the stroke is visible.

import { DrawSVGPlugin } from "gsap/DrawSVGPlugin";
gsap.registerPlugin(DrawSVGPlugin);

// 0 to 100% (default)
gsap.from("path", { drawSVG: 0, duration: 2 });

// Specific percentage range "start end"
gsap.to("path", { drawSVG: "0% 50%", duration: 1 });
gsap.to("path", { drawSVG: "25% 75%", duration: 1 }); // moving window

// Reverse direction
gsap.from("path", { drawSVG: "100% 100%", duration: 2 }); // draw from end

// Works on circles, ellipses, lines, polylines, etc.
gsap.from("circle", { drawSVG: 0, duration: 1 });

MorphSVGPlugin

Free since GSAP 3.13. Morphs one SVG shape into another.

import { MorphSVGPlugin } from "gsap/MorphSVGPlugin";
gsap.registerPlugin(MorphSVGPlugin);

// Morph a path to another path (by selector or d attribute string)
gsap.to("#shape1", { morphSVG: "#shape2", duration: 1 });

// Use a raw d string as the target shape
gsap.to("#shape1", {
  morphSVG: "M0,0 C50,100 150,100 200,0",
  duration: 1.5,
});

// Control alignment and shaping
gsap.to("#blob", {
  morphSVG: {
    shape: "#targetBlob",
    type: "rotational",  // "linear" (default) or "rotational"
    origin: "50% 50%",
    map: "position",     // "size", "position", or "complexity"
  },
  duration: 2,
  ease: "power2.inOut",
});

// convertToPath() — convert shapes to paths for morphing
MorphSVGPlugin.convertToPath("circle, rect, ellipse, polygon, polyline, line");

MotionPathPlugin

Move elements along an SVG path.

import { MotionPathPlugin } from "gsap/MotionPathPlugin";
gsap.registerPlugin(MotionPathPlugin);

// Follow an SVG <path>
gsap.to(".dot", {
  duration: 4,
  ease: "none",
  motionPath: {
    path: "#track",
    align: "#track",
    alignOrigin: [0.5, 0.5],
    autoRotate: true,     // face direction of travel
    start: 0,             // 0–1
    end: 1,               // 0–1
  },
});

// Array of coordinate objects
gsap.to(".dot", {
  duration: 2,
  motionPath: [
    { x: 0,   y: 0   },
    { x: 100, y: -80 },
    { x: 200, y: 0   },
    { x: 300, y: 80  },
  ],
  ease: "power1.inOut",
});

// Get raw path data
const rawPath = MotionPathPlugin.getRawPath("#myPath");
MotionPathPlugin.cacheRawPathMeasurements(rawPath);
const point = MotionPathPlugin.getPositionOnPath(rawPath, 0.5); // {x, y, angle}

GSAP Utility Functions

gsap.utils is a collection of pure helper functions — no animation involved.

clamp

const clamp = gsap.utils.clamp(0, 100);
clamp(150);  // → 100
clamp(-10);  // → 0
clamp(50);   // → 50

// Inline
gsap.utils.clamp(0, 100, 150); // → 100

snap

// Snap to nearest increment
const snap10 = gsap.utils.snap(10);
snap10(73); // → 70
snap10(76); // → 80

// Snap to closest value in an array
const snapVals = gsap.utils.snap([0, 25, 50, 75, 100]);
snapVals(38); // → 25

// Inline
gsap.utils.snap(5, 17); // → 15

mapRange

Maps a value from one range to another.

// mapRange(inMin, inMax, outMin, outMax, value)
gsap.utils.mapRange(0, 100, 0, 1, 50);    // → 0.5
gsap.utils.mapRange(0, 100, -50, 50, 75); // → 25

// Curried (omit value)
const mapper = gsap.utils.mapRange(0, 360, 0, 1);
mapper(180); // → 0.5

normalize

Shorthand for mapRange(min, max, 0, 1).

const norm = gsap.utils.normalize(0, 100);
norm(50); // → 0.5
norm(25); // → 0.25

interpolate

Interpolates between values, arrays, or objects.

// Two numbers
gsap.utils.interpolate(0, 100, 0.5);   // → 50

// Two colors
gsap.utils.interpolate("#ff0000", "#0000ff", 0.5); // → midpoint color

// Arrays of objects
const lerp = gsap.utils.interpolate(
  { r: 255, g: 0,   b: 0 },
  { r: 0,   g: 0,   b: 255 },
);
lerp(0.5); // → { r: 127.5, g: 0, b: 127.5 }

// Array of values (progress 0–1 across all stops)
gsap.utils.interpolate([0, 50, 200, 100], 0.5); // → 125 (progress 0.5 lands mid-way through the 50→200 segment)

pipe

Compose multiple utility functions left-to-right.

const process = gsap.utils.pipe(
  gsap.utils.clamp(0, 100),
  gsap.utils.snap(10),
  gsap.utils.mapRange(0, 100, 0, 1),
);
process(73); // clamp(73)=73, snap(73)=70, map(70)=0.7

wrap

Wraps a value around an array or range (loops).

const wrap = gsap.utils.wrap(0, 10);
wrap(11); // → 1
wrap(-1); // → 9
wrap(5);  // → 5

// Array wrap
const wrapArr = gsap.utils.wrap(["a", "b", "c"]);
wrapArr(0); // → "a"
wrapArr(4); // → "b"

wrapYoyo

Like wrap but bounces back and forth.

const wrapY = gsap.utils.wrapYoyo(0, 10);
wrapY(12); // → 8 (bounced back)

distribute

Distributes values across an array based on easing — used internally by stagger.

const dist = gsap.utils.distribute({
  base: 0,
  amount: 1,
  from: "center",
  ease: "power1.inOut",
  axis: null,
  grid: "auto",
});
// Returns a function(index, target, targets) → value

random

// Random number (min, max)
gsap.utils.random(0, 100);    // e.g. 67.3
gsap.utils.random(0, 100, 1); // snapped to increment of 1 (integer)
gsap.utils.random(0, 100, 5); // snapped to nearest 5

// Random from array
gsap.utils.random(["red", "green", "blue"]); // one at random

// Reusable function — a boolean last arg means returnFunction, NOT snapping
const rand = gsap.utils.random(10, 50, true);
rand(); // e.g. 34.2
const randInt = gsap.utils.random(10, 50, 1, true); // snapped AND curried

toArray

Normalize any target to a real Array.

gsap.utils.toArray(".item");                         // NodeList → Array
gsap.utils.toArray(document.querySelectorAll("li")); // same
gsap.utils.toArray(".a, .b");                        // combined selector
gsap.utils.toArray([refA.current, refB.current]);    // already array-like

selector

Creates a scoped selector function (replaces document.querySelector within a root).

const q = gsap.utils.selector(containerRef.current);
// or
const q = gsap.utils.selector(".wrapper");

gsap.to(q(".box"), { x: 100 });   // only .box inside .wrapper
gsap.to(q(".title"), { y: -20 });

unitize

Adds units to a function's output.

const clampPx = gsap.utils.unitize(gsap.utils.clamp(0, 500), "px");
clampPx(300); // → "300px"
clampPx(600); // → "500px"

checkPrefix

Returns the vendor-prefixed version of a CSS property (rarely needed in modern browsers).

gsap.utils.checkPrefix("transform"); // "transform" or "webkitTransform"

Flip Plugin

Animate between two DOM states using the FLIP technique (First, Last, Invert, Play).

import { Flip } from "gsap/Flip";
gsap.registerPlugin(Flip);

// 1. Capture state BEFORE the DOM change
const state = Flip.getState(".card");

// 2. Make your DOM / CSS changes
container.classList.toggle("expanded");
cards.forEach(c => c.classList.toggle("big"));

// 3. Animate FROM old state TO new state
Flip.from(state, {
  duration: 0.6,
  ease: "power2.inOut",
  stagger: 0.05,
  absolute: true,      // take elements out of flow during animation
  onComplete: () => console.log("flip done"),
});
// Flip.fit() — morph one element to match another's position/size
Flip.fit("#target", "#destination", { duration: 1, ease: "power2.inOut" });

// Flip with scale (animates width/height via scale instead of layout)
Flip.from(state, { scale: true, duration: 0.5 });

SplitText

Splits text into lines, words, and/or characters for staggered text animation. Free since GSAP 3.13, when it was also rewritten — smaller, screen-reader-friendly aria handling, responsive autoSplit, and built-in masking.

import { SplitText } from "gsap/SplitText";
gsap.registerPlugin(SplitText);

const split = SplitText.create(".headline", { type: "chars, words, lines" });

gsap.from(split.chars, {
  y: 20,
  opacity: 0,
  stagger: 0.02,
  duration: 0.6,
  ease: "power2.out",
});

split.revert(); // restore the original text/DOM
// Responsive: re-split when fonts load or lines rewrap, and rebuild the tween
SplitText.create(".headline", {
  type: "lines",
  autoSplit: true,
  mask: "lines", // wraps each line in an overflow clip for reveal effects
  onSplit(self) {
    return gsap.from(self.lines, {
      yPercent: 100,
      stagger: 0.1,
      duration: 0.8,
      ease: "power3.out",
    }); // returned animations are auto-reverted before each re-split
  },
});