GSAP Cheatsheet

SVG and Utilities

Use this GSAP reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

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
  },
});