Official GSAP skill for GSAP plugins — registration, ScrollToPlugin, ScrollSmoother, Flip, Draggable, Inertia, Observer, SplitText, ScrambleText, DrawSVG, MorphSVG, MotionPath, CustomEase, EasePack, GSDevTools. Use when the user asks about a GSAP plugin, scroll-to, flip animations, draggable, SVG drawing/morphing, text splitting, or plugin registration.
Apply when using or reviewing code that uses GSAP plugins: registering plugins, scroll-to, flip/FLIP animations, draggable elements, SVG (DrawSVG, MorphSVG, MotionPath), text (SplitText, ScrambleText), physics, easing plugins (CustomEase, EasePack), or GSDevTools. ScrollTrigger has its own skill (gsap-scrolltrigger).
Related skills: For core tweens use gsap-core; for ScrollTrigger use gsap-scrolltrigger; for React use gsap-react.
Register each plugin once before use:
import gsap from "gsap";
import { ScrollToPlugin } from "gsap/ScrollToPlugin";
import { Flip } from "gsap/Flip";
import { Draggable } from "gsap/Draggable";
gsap.registerPlugin(ScrollToPlugin, Flip, Draggable);
Animate scroll position (window or scrollable element):
gsap.registerPlugin(ScrollToPlugin);
gsap.to(window, { duration: 1, scrollTo: { y: 500 } });
gsap.to(window, { duration: 1, scrollTo: { y: "#section", offsetY: 50 } });
gsap.to(scrollContainer, { duration: 1, scrollTo: { x: "max" } });
| Option | Description |
|---|---|
x, y | Target position (number) or "max" for maximum |
element | Selector or element to scroll to |
offsetX, offsetY | Pixel offset from the target position |
Smooth scroll wrapper. Requires ScrollTrigger and a specific DOM structure:
<body>
<div id="smooth-wrapper">
<div id="smooth-content">
<!-- ALL YOUR CONTENT HERE -->
</div>
</div>
</body>
Register after ScrollTrigger. See GSAP docs for full setup.
Capture layout state → change DOM → animate from old state to new (FLIP pattern):
gsap.registerPlugin(Flip);
const state = Flip.getState(".item");
// change DOM: reorder, add/remove, change classes
Flip.from(state, { duration: 0.5, ease: "power2.inOut" });
| Option | Description |
|---|---|
absolute | Use position: absolute during the flip |
scale | Scale elements to fit (default true) |
duration, ease | Standard tween options |
Makes elements draggable, spinnable, or throwable:
gsap.registerPlugin(Draggable, InertiaPlugin);
Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true });
Draggable.create(".knob", { type: "rotation" });
| Option | Description |
|---|---|
type | "x", "y", "x,y", "rotation", "scroll" |
bounds | Element, selector, or { minX, maxX, minY, maxY } |
inertia | true for throw/momentum (requires InertiaPlugin) |
edgeResistance | 0–1; resistance past bounds |
onDragStart, onDrag, onDragEnd | Callbacks |
Works with Draggable for momentum after release, or track velocity of any property:
gsap.registerPlugin(Draggable, InertiaPlugin);
Draggable.create(".box", { type: "x,y", inertia: true });
// or track velocity manually:
InertiaPlugin.track(".box", "x");
gsap.to(obj, { inertia: { x: "auto" } }); // glide to stop
Normalizes pointer/scroll input across devices for custom gesture logic:
gsap.registerPlugin(Observer);
Observer.create({
target: "#area",
onUp: () => {},
onDown: () => {},
onLeft: () => {},
onRight: () => {},
tolerance: 10
});
| Option | Description |
|---|---|
target | Element or selector to observe |
onUp/Down/Left/Right | Callbacks when swipe/scroll passes tolerance |
tolerance | Pixels before direction is detected (default 10) |
type | "touch", "pointer", "wheel" |
Splits element text into chars, words, and/or lines for staggered animation:
gsap.registerPlugin(SplitText);
const split = SplitText.create(".heading", { type: "words, chars" });
gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.03, duration: 0.4 });
// later:
split.revert();
With autoSplit for responsive re-splitting:
SplitText.create(".split", {
type: "lines",
autoSplit: true,
onSplit(self) {
return gsap.from(self.lines, { y: 100, opacity: 0, stagger: 0.05, duration: 0.5 });
}
});
Key config:
| Option | Description |
|---|---|
type | "chars", "words", "lines" (comma-separated) |
charsClass, wordsClass, linesClass | CSS class on each split element |
aria | "auto" (default), "hidden", "none" |
autoSplit | Re-split on font load or width change |
onSplit(self) | Callback; return a tween for auto-sync on re-split |
mask | "lines", "words", or "chars" for clip-mask reveal |
Scramble/glitch text animation:
gsap.registerPlugin(ScrambleTextPlugin);
gsap.to(".text", {
duration: 1,
scrambleText: { text: "New message", chars: "01", revealDelay: 0.5 }
});
Reveals/hides SVG strokes by animating stroke-dashoffset/stroke-dasharray:
gsap.registerPlugin(DrawSVGPlugin);
// draw from nothing to full stroke
gsap.from("#path", { duration: 1, drawSVG: 0 });
// explicit segment: 0–0 to 0–100%
gsap.fromTo("#path", { drawSVG: "0% 0%" }, { drawSVG: "0% 100%", duration: 1 });
// stroke only in the middle
gsap.to("#path", { duration: 1, drawSVG: "20% 80%" });
Required: Element must have a visible stroke and stroke-width set in CSS/SVG.
Morphs one SVG shape into another by animating the d attribute:
gsap.registerPlugin(MorphSVGPlugin);
// Convert primitives to path first:
MorphSVGPlugin.convertToPath("circle, rect, ellipse, line");
gsap.to("#diamond", { duration: 1, morphSVG: "#lightning", ease: "power2.inOut" });
// or object form:
gsap.to("#diamond", {
duration: 1,
morphSVG: { shape: "#lightning", type: "rotational", shapeIndex: 2 }
});
| Option | Description |
|---|---|
shape | Target: selector, element, or raw path string |
type | "linear" (default) or "rotational" |
shapeIndex | Offset for start point mapping; use "log" to find good value |
map | Segment matching: "size" (default), "position", "complexity" |
Animate an element along an SVG path:
gsap.registerPlugin(MotionPathPlugin);
gsap.to(".dot", {
duration: 2,
motionPath: { path: "#path", align: "#path", alignOrigin: [0.5, 0.5], autoRotate: true }
});
Custom easing curves (cubic-bezier or SVG path):
gsap.registerPlugin(CustomEase);
const myEase = CustomEase.create("hop", "M0,0 C0,0 0.056,0.442 0.175,0.442 0.294,0.442 0.332,0 0.332,0 0.332,0 0.414,1 0.671,1 0.991,1 1,0 1,0");
gsap.to(".item", { x: 100, ease: myEase, duration: 1 });
// simple cubic-bezier:
const ease2 = CustomEase.create("my-ease", ".17,.67,.83,.67");
Adds extra named eases (SlowMo, RoughEase, ExpoScaleEase). Register and use the ease names in tweens.
Wiggle/shake and bounce-style easing with configurable strength. Register before use.
gsap.registerPlugin(Physics2DPlugin);
gsap.to(".ball", {
duration: 2,
physics2D: { velocity: 250, angle: 80, gravity: 500 }
});
gsap.registerPlugin(PhysicsPropsPlugin);
gsap.to(".obj", {
duration: 2,
physicsProps: {
x: { velocity: 100, end: 300 },
y: { velocity: -50, acceleration: 200 }
}
});
UI for scrubbing timelines during development. Remove before production.
gsap.registerPlugin(GSDevTools);
GSDevTools.create({ animation: tl });
gsap.registerPlugin() before first use.Flip.getState() → DOM change → Flip.from() for layout transitions.Draggable + InertiaPlugin for drag with momentum.split.revert()) when components unmount.