| name | gsap |
| description | Use this skill whenever the user wants to animate anything using GSAP (GreenSock Animation Platform). Trigger for any request involving: GSAP animations, tweens, timelines, ScrollTrigger, SplitText, Flip, Draggable, MorphSVG, MotionPath, scroll-based animations, web page animations, interactive UI animations, SVG animations, text animations, or any JavaScript animation library work. Also trigger when the user asks to "animate", "transition", or "add motion" to HTML/React/web content and GSAP would be the best tool for the job. Always consult this skill before writing any GSAP code.
|
GSAP Animation Skill
GSAP (GreenSock Animation Platform) v3 — the industry-standard JavaScript animation library.
Docs: https://gsap.com/docs/v3/GSAP/
Cheatsheet: https://gsap.com/cheatsheet
Plugins reference index: see references/plugins.md
Special properties reference: see references/special-properties.md
Installation
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<script>gsap.registerPlugin(ScrollTrigger);</script>
npm install gsap
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
Core Concepts
Tween — the animation workhorse
A tween animates one or more properties of one or more targets over time.
gsap.to(".box", { x: 200, rotation: 360, duration: 1, ease: "power2.out" });
gsap.from(".box", { opacity: 0, y: -50, duration: 0.8 });
gsap.fromTo(".box", { opacity: 0, scale: 0.5 }, { opacity: 1, scale: 1, duration: 1 });
gsap.set(".box", { x: 100, opacity: 0 });
Timeline — sequencing container
A timeline holds and sequences multiple tweens.
const tl = gsap.timeline({ defaults: { ease: "power2.out", duration: 0.8 } });
tl.from(".heading", { y: -30, opacity: 0 })
.from(".subtitle", { y: -20, opacity: 0 })
.from(".btn", { scale: 0.8, opacity: 0 });
tl.to(".a", { x: 100 })
.to(".b", { x: 100 }, "<")
.to(".c", { x: 100 }, "<0.2")
.to(".d", { x: 100 }, "+=0.5")
.to(".e", { x: 100 }, 2)
.to(".f", { x: 100 }, "myLabel");
Position Parameter Quick Reference
| Value | Meaning |
|---|
| (none) | End of timeline |
"<" | Start of previous tween |
">" | End of previous tween |
"<0.5" | 0.5s after previous starts |
"-=0.3" | 0.3s before timeline end |
"+=0.3" | 0.3s after timeline end |
2 | Absolute time 2s |
"label" | At named label |
Common Animatable Properties
gsap.to(".box", {
x: 100,
y: 50,
xPercent: -50,
yPercent: -50,
rotation: 360,
rotationX: 45,
rotationY: 45,
scale: 1.5,
scaleX: 2,
scaleY: 0.5,
skewX: 15,
skewY: 10,
opacity: 0,
width: "200px",
backgroundColor: "#ff0000",
borderRadius: "50%",
color: "blue",
duration: 1,
delay: 0.5,
ease: "power2.inOut",
repeat: -1,
yoyo: true,
stagger: 0.1,
});
Easing
"none"
"power1.out"
"power2.out"
"power3.out"
"power4.out"
"back.out(1.7)"
"elastic.out(1, 0.3)"
"bounce.out"
"circ.out"
"expo.out"
"sine.out"
"steps(5)"
CustomEase.create("myEase", "M0,0 C0.126,0.382 0.282,0.674 0.44,0.822...")
Special Properties (Callbacks & Controls)
gsap.to(".box", {
x: 200,
duration: 1,
onStart: () => console.log("started"),
onComplete: () => console.log("done"),
onUpdate: () => console.log("updating"),
onRepeat: () => console.log("repeating"),
stagger: {
amount: 1,
from: "center",
grid: "auto",
ease: "power1.in",
},
id: "myTween",
paused: true,
immediateRender: false,
overwrite: "auto",
});
Tween & Timeline Control Methods
const tween = gsap.to(".box", { x: 200, duration: 2, paused: true });
const tl = gsap.timeline({ paused: true });
tween.play();
tween.pause();
tween.reverse();
tween.restart();
tween.resume();
tween.seek(0.5);
tl.seek("myLabel");
tween.progress(0.5);
tween.time(1);
tween.timeScale(2);
tween.timeScale(0.5);
tween.duration();
tween.progress();
tween.isActive();
tween.kill();
gsap.killTweensOf(".box");
ScrollTrigger
Read references/plugins.md → ScrollTrigger section for full API.
gsap.registerPlugin(ScrollTrigger);
gsap.to(".box", {
x: 500,
scrollTrigger: {
trigger: ".box",
start: "top 80%",
end: "bottom 20%",
scrub: true,
pin: true,
markers: true,
}
});
ScrollTrigger.create({
trigger: ".section",
start: "top center",
onEnter: () => console.log("entered"),
onLeave: () => console.log("left"),
onEnterBack: () => console.log("re-entered"),
});
start/end format: "[triggerPosition] [scrollerPosition]"
Trigger positions: top, center, bottom, Npx, N%
Scroller positions: top, center, bottom, Npx, N%
React Usage
import { useRef, useLayoutEffect } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(useGSAP);
function MyComponent() {
const container = useRef();
useGSAP(() => {
gsap.from(".box", { opacity: 0, y: 30, duration: 0.8 });
}, { scope: container });
return (
<div ref={container}>
<div className="box">Hello</div>
</div>
);
}
gsap.matchMedia() — Responsive Animations
const mm = gsap.matchMedia();
mm.add("(min-width: 800px)", () => {
gsap.to(".hero", { x: 200, duration: 1 });
});
mm.add("(max-width: 799px)", () => {
gsap.to(".hero", { y: 50, duration: 0.5 });
});
mm.revert();
gsap.context() — Scoping & Cleanup
const ctx = gsap.context(() => {
gsap.from(".card", { opacity: 0, y: 30, stagger: 0.1 });
gsap.to(".bg", { backgroundPosition: "50% 100%", duration: 5, repeat: -1 });
}, containerRef);
ctx.revert();
Utility Methods
gsap.utils.clamp(0, 100, 150);
gsap.utils.mapRange(0,1, 0,100, 0.5);
gsap.utils.interpolate("red","blue", 0.5);
gsap.utils.random(0, 100);
gsap.utils.random(["a","b","c"]);
gsap.utils.snap(5, 13);
gsap.utils.wrap(0, 5, 6);
gsap.utils.toArray(".items");
Common Patterns
Page load entrance animation
const tl = gsap.timeline({ defaults: { ease: "power3.out", duration: 0.8 } });
tl.from("nav", { y: -60, opacity: 0 })
.from(".hero-title", { y: 40, opacity: 0 }, "-=0.4")
.from(".hero-subtitle", { y: 30, opacity: 0 }, "-=0.5")
.from(".hero-btn", { scale: 0.9, opacity: 0 }, "-=0.4");
Scroll reveal (stagger cards)
gsap.from(".card", {
scrollTrigger: {
trigger: ".cards-section",
start: "top 75%",
},
opacity: 0,
y: 50,
stagger: 0.15,
duration: 0.8,
ease: "power2.out",
});
Infinite loop animation
gsap.to(".spinner", {
rotation: 360,
duration: 1,
ease: "none",
repeat: -1,
});
Hover animation
const btn = document.querySelector(".btn");
btn.addEventListener("mouseenter", () => gsap.to(btn, { scale: 1.05, duration: 0.2 }));
btn.addEventListener("mouseleave", () => gsap.to(btn, { scale: 1, duration: 0.2 }));
Key Rules & Best Practices
- Use transform shortcuts (
x, y, rotation, scale) not raw CSS transform. GSAP optimizes these for performance.
- Use
gsap.context() in React/frameworks — ensures proper cleanup.
- Register plugins with
gsap.registerPlugin() before use — do it once at app root.
overwrite: "auto" to avoid conflicts when re-triggering tweens.
immediateRender: false on gsap.from() when multiple tweens target the same element to prevent flicker.
- Remove ScrollTrigger markers (
markers: true) before production.
- Use
scrub: true for scroll-linked animations; use toggleActions for trigger-only animations.
- Prefer timelines over multiple standalone tweens for sequenced animations — easier to manage and control.
Plugin Reference
For detailed plugin APIs (ScrollTrigger, SplitText, Flip, Draggable, MorphSVG, MotionPath, etc.), read:
📄 references/plugins.md
For complete special properties and vars options:
📄 references/special-properties.md