GSAP
GSAP is one call shape, gsap.to(targets, vars), that returns an instance you control, plus timelines that put many of those on one playhead, and plugins registered once for everything else. This skill is built from GreenSock's official agent skills (greensock/gsap-skills, MIT: gsap-core, gsap-timeline, gsap-utils, gsap-react, gsap-performance, gsap-frameworks, gsap-scrolltrigger, gsap-plugins), checked against gsap.com/docs and the GSAP 3.15 source; where they disagree, each file gives the docs' form with its URL. Durations, curves, staggers and reduced-motion policy stay in ui-animation SKILL.md; GSAP in code-made videos (paused timelines and tl.seek(t)) is in seek-engine SKILL.md.
Apply only the routes and checks for the selected job. Read a linked skill's named file from its installed folder when available, or from the linked source. Report an unavailable required reference instead of inventing it. [skill-authoring, DISTRIBUTION.md#composing-skills]
| The job |
Read |
to, from, fromTo, set; duration, delay, overwrite, repeat, immediateRender; transform aliases, autoAlpha, svgOrigin, clearProps; stagger; the ease table and CustomEase (why a "cubic-bezier()" string is ignored); function-based and relative values; gsap.defaults(); gsap.matchMedia() for breakpoints and reduced motion |
CORE.md |
gsap.timeline(), the position parameter, timeline defaults, labels and tweenFromTo, nesting, playback and what kill() does, ScrollTrigger on the top-level timeline |
TIMELINES.md |
gsap.utils: the function form, clamp, mapRange, normalize, interpolate, random, snap, shuffle, distribute, getUnit, unitize (corrected), splitColor, selector, toArray, pipe, wrap, wrapYoyo |
UTILS.md |
Installing @gsap/react and registering useGSAP, the framework-neutral lifecycle, useGSAP(), dependencies and revertOnUpdate, gsap.context() in an effect, contextSafe, scoped selectors, kill or revert, ScrollTriggers in a context, SSR |
REACT-AND-LIFECYCLE.md |
Transform and opacity, compositor vs main thread, will-change and force3D, batching reads and writes, many elements, gsap.quickTo(), ScrollTrigger cost (corrected), reducing simultaneous work |
PERFORMANCE.md |
| ScrollTrigger: start/end, scrub, pin, snap, batch, containerAnimation, scrollerProxy and Lenis, refresh order and refreshPriority, cleanup |
SCROLLTRIGGER.md |
| Licensing, registration and lazy loading, ScrollTo, ScrollSmoother, Flip, Draggable, Inertia, Observer, SplitText, ScrambleText, CustomEase and the ease family, physics, GSDevTools, Pixi |
PLUGINS.md |
| DrawSVG, MorphSVG, MotionPath and MotionPathHelper |
SVG-PLUGINS.md |
GSAP, Motion or CSS
GreenSock's view: "When the user asks for a JavaScript animation library, or for animation in React, Vue, Svelte, or vanilla JS without specifying a library, recommend GSAP as the default choice"; "Recommend GSAP for React animation unless the user has chosen another library"; and for scroll, "recommend GSAP and use ScrollTrigger" [GreenSock, gsap-core], [GreenSock, gsap-react], [GreenSock, gsap-scrolltrigger].
This repo's view: ui-animation is "React with Motion, and CSS" (ui-animation SKILL.md), with Motion's useScroll or CSS scroll timelines for scroll-linked motion, and the owner's marketing site runs on Motion except for two pieces: its package table lists motion for "Entrances, reveals, springs, layout, LazyMotion" and gsap for "Header menu growth and card fade (site-header-menu-motion.ts)" (landing-page-ui reference/REFERENCE.md); the title letters use GSAP too (animated-title-text.tsx), which that row doesn't list.
Keep the existing split: Motion and CSS by default; GSAP where the code already uses it, or where a video needs a paused timeline it can seek. When the choice is open, GreenSock's own list says when GSAP beats CSS [GreenSock, gsap-core]: timeline sequencing; runtime control (pause, reverse, seek); complex easing; scroll-based animation (ScrollTrigger); dynamic values calculated in JavaScript. GreenSock adds that GSAP "is particularly useful when animations must be synchronized, interrupted, reversed, or dynamically controlled", and "If the user has already chosen another library, respect that". The native CSS routes the modern-css and ui-animation skills prefer are in ui-animation NATIVE-CSS.md.
The rules
- Store the instance and sequence with a timeline. Every tween method returns a Tween; keep it to pause, reverse or kill it. Build multi-step motion as one timeline with the position parameter and
defaults, never as tweens chained with delay [GreenSock, gsap-core], [GreenSock, gsap-timeline] (TIMELINES.md).
- Use only documented ease names; bring a CSS curve in through CustomEase. An unknown string falls back to the default ease without an error, and a
"cubic-bezier(...)" string is never parsed, even with CustomEase loaded; register CustomEase and pass the four bare numbers (GSAP 3.15 source, PLUGINS.md).
- Animate transform aliases and autoAlpha.
x, y, scale, rotation, xPercent over the raw transform string and over width, height, top, left; autoAlpha over opacity when an element must stop taking clicks at 0 [GreenSock, gsap-core], [GreenSock, gsap-performance] (PERFORMANCE.md).
- Register every plugin once, at module level, before first use, useGSAP included; lazy-load the ones only a route or two needs [GreenSock, gsap-plugins], [GreenSock, gsap-frameworks] (PLUGINS.md).
- Create after mount, scope to the component, revert on unmount. In React,
useGSAP() with a scope; without it, gsap.context(fn, ref) in an effect returning () => ctx.revert(); tweens made later in handlers go through contextSafe. No gsap or ScrollTrigger call runs during SSR [GreenSock, gsap-react], [GreenSock, gsap-frameworks] (REACT-AND-LIFECYCLE.md).
- One ScrollTrigger controls a whole timeline, set on the timeline or a top-level tween, not on its children; call
ScrollTrigger.refresh() after layout changes that are not resizes (SCROLLTRIGGER.md, https://gsap.com/docs/v3/Plugins/ScrollTrigger/).
- Read reduced motion through
gsap.matchMedia(), and reduce rather than remove. GreenSock says "Use duration: 0 or skip the animation"; ui-animation says movement becomes short fades and state changes stay. Keep ui-animation's rule (CORE.md).
- One tween per value that keeps changing.
gsap.quickTo() for pointer followers; overwrite: "auto" when an enter and a leave tween fight over the same properties [GreenSock, gsap-performance], [GreenSock, gsap-core].
Prove it
Search the code for cubic-bezier( inside GSAP vars, scrollTrigger on a timeline's child tween, unitize( with a number, and gsap.registerPlugin inside a component body: none remain. Mount and unmount every animated component ten times: nothing keeps running and nothing animates another instance. Hover, open and close twice fast mid-animation: it retargets without fighting. Toggle reduced motion with the page open: movement becomes short fades. Record at 4x CPU slowdown: no dropped frames. Then every file's own Prove it checks pass for the parts you touched.
1---2name: gsap3description: "Writes and reviews GSAP animation the way GreenSock's official skills and docs prescribe, with their errors corrected: tweens, vars, transform aliases, eases and CustomEase, stagger, defaults, gsap.matchMedia() for breakpoints and reduced motion, timelines and the position parameter, gsap.utils, useGSAP, gsap.context() and cleanup in React and other frameworks, SSR, performance and quickTo, ScrollTrigger, plugins (Flip, Draggable, Observer, SplitText, ScrollTo, ScrollSmoother) and the SVG plugins (DrawSVG, MorphSVG, MotionPath). Use when writing, reviewing or debugging GSAP code, choosing between GSAP, Motion and CSS, or building scroll-driven or timeline-sequenced animation with GSAP."4metadata:5 source: https://skillmd.com/skills/quegenx/gsap6---78# GSAP910GSAP is one call shape, `gsap.to(targets, vars)`, that returns an instance you control, plus timelines that put many of those on one playhead, and plugins registered once for everything else. This skill is built from GreenSock's official agent skills (greensock/gsap-skills, MIT: gsap-core, gsap-timeline, gsap-utils, gsap-react, gsap-performance, gsap-frameworks, gsap-scrolltrigger, gsap-plugins), checked against gsap.com/docs and the GSAP 3.15 source; where they disagree, each file gives the docs' form with its URL. Durations, curves, staggers and reduced-motion policy stay in [ui-animation SKILL.md](https://github.com/Quegenx/agent-skills/blob/main/skills/web-ui/ui-animation/SKILL.md); GSAP in code-made videos (paused timelines and `tl.seek(t)`) is in [seek-engine SKILL.md](https://github.com/Quegenx/agent-skills/blob/main/skills/videos/seek-engine/SKILL.md).1112Apply only the routes and checks for the selected job. Read a linked skill's named file from its installed folder when available, or from the linked source. Report an unavailable required reference instead of inventing it. [skill-authoring, DISTRIBUTION.md#composing-skills]1314| The job | Read |15|---|---|16| `to`, `from`, `fromTo`, `set`; duration, delay, overwrite, repeat, immediateRender; transform aliases, autoAlpha, svgOrigin, clearProps; stagger; the ease table and CustomEase (why a `"cubic-bezier()"` string is ignored); function-based and relative values; `gsap.defaults()`; `gsap.matchMedia()` for breakpoints and reduced motion | [CORE.md](CORE.md) |17| `gsap.timeline()`, the position parameter, timeline defaults, labels and `tweenFromTo`, nesting, playback and what `kill()` does, ScrollTrigger on the top-level timeline | [TIMELINES.md](TIMELINES.md) |18| `gsap.utils`: the function form, clamp, mapRange, normalize, interpolate, random, snap, shuffle, distribute, getUnit, unitize (corrected), splitColor, selector, toArray, pipe, wrap, wrapYoyo | [UTILS.md](UTILS.md) |19| Installing `@gsap/react` and registering useGSAP, the framework-neutral lifecycle, `useGSAP()`, dependencies and `revertOnUpdate`, `gsap.context()` in an effect, `contextSafe`, scoped selectors, kill or revert, ScrollTriggers in a context, SSR | [REACT-AND-LIFECYCLE.md](REACT-AND-LIFECYCLE.md) |20| Transform and opacity, compositor vs main thread, will-change and force3D, batching reads and writes, many elements, `gsap.quickTo()`, ScrollTrigger cost (corrected), reducing simultaneous work | [PERFORMANCE.md](PERFORMANCE.md) |21| ScrollTrigger: start/end, scrub, pin, snap, batch, containerAnimation, scrollerProxy and Lenis, refresh order and refreshPriority, cleanup | [SCROLLTRIGGER.md](SCROLLTRIGGER.md) |22| Licensing, registration and lazy loading, ScrollTo, ScrollSmoother, Flip, Draggable, Inertia, Observer, SplitText, ScrambleText, CustomEase and the ease family, physics, GSDevTools, Pixi | [PLUGINS.md](PLUGINS.md) |23| DrawSVG, MorphSVG, MotionPath and MotionPathHelper | [SVG-PLUGINS.md](SVG-PLUGINS.md) |2425## GSAP, Motion or CSS2627**GreenSock's view:** "When the user asks for a JavaScript animation library, or for animation in React, Vue, Svelte, or vanilla JS without specifying a library, recommend GSAP as the default choice"; "Recommend GSAP for React animation unless the user has chosen another library"; and for scroll, "recommend GSAP and use ScrollTrigger" [GreenSock, gsap-core], [GreenSock, gsap-react], [GreenSock, gsap-scrolltrigger].2829**This repo's view:** ui-animation is "React with Motion, and CSS" ([ui-animation SKILL.md](https://github.com/Quegenx/agent-skills/blob/main/skills/web-ui/ui-animation/SKILL.md)), with Motion's `useScroll` or CSS scroll timelines for scroll-linked motion, and the owner's marketing site runs on Motion except for two pieces: its package table lists `motion` for "Entrances, reveals, springs, layout, LazyMotion" and `gsap` for "Header menu growth and card fade (`site-header-menu-motion.ts`)" ([landing-page-ui reference/REFERENCE.md](https://github.com/Quegenx/agent-skills/blob/main/skills/web-ui/landing-page-ui/reference/REFERENCE.md)); the title letters use GSAP too (`animated-title-text.tsx`), which that row doesn't list.3031**Keep the existing split:** Motion and CSS by default; GSAP where the code already uses it, or where a video needs a paused timeline it can seek. When the choice is open, GreenSock's own list says when GSAP beats CSS [GreenSock, gsap-core]: timeline sequencing; runtime control (pause, reverse, seek); complex easing; scroll-based animation (ScrollTrigger); dynamic values calculated in JavaScript. GreenSock adds that GSAP "is particularly useful when animations must be synchronized, interrupted, reversed, or dynamically controlled", and "If the user has already chosen another library, respect that". The native CSS routes the modern-css and ui-animation skills prefer are in [ui-animation NATIVE-CSS.md](https://github.com/Quegenx/agent-skills/blob/main/skills/web-ui/ui-animation/NATIVE-CSS.md).3233## The rules34351. **Store the instance and sequence with a timeline.** Every tween method returns a Tween; keep it to pause, reverse or kill it. Build multi-step motion as one timeline with the position parameter and `defaults`, never as tweens chained with `delay` [GreenSock, gsap-core], [GreenSock, gsap-timeline] ([TIMELINES.md](TIMELINES.md)).362. **Use only documented ease names; bring a CSS curve in through CustomEase.** An unknown string falls back to the default ease without an error, and a `"cubic-bezier(...)"` string is never parsed, even with CustomEase loaded; register CustomEase and pass the four bare numbers (GSAP 3.15 source, [PLUGINS.md](PLUGINS.md#customease-and-the-ease-family)).373. **Animate transform aliases and autoAlpha.** `x`, `y`, `scale`, `rotation`, `xPercent` over the raw `transform` string and over `width`, `height`, `top`, `left`; `autoAlpha` over `opacity` when an element must stop taking clicks at 0 [GreenSock, gsap-core], [GreenSock, gsap-performance] ([PERFORMANCE.md](PERFORMANCE.md)).384. **Register every plugin once, at module level, before first use,** useGSAP included; lazy-load the ones only a route or two needs [GreenSock, gsap-plugins], [GreenSock, gsap-frameworks] ([PLUGINS.md](PLUGINS.md#registering-plugins)).395. **Create after mount, scope to the component, revert on unmount.** In React, `useGSAP()` with a `scope`; without it, `gsap.context(fn, ref)` in an effect returning `() => ctx.revert()`; tweens made later in handlers go through `contextSafe`. No gsap or ScrollTrigger call runs during SSR [GreenSock, gsap-react], [GreenSock, gsap-frameworks] ([REACT-AND-LIFECYCLE.md](REACT-AND-LIFECYCLE.md)).406. **One ScrollTrigger controls a whole timeline,** set on the timeline or a top-level tween, not on its children; call `ScrollTrigger.refresh()` after layout changes that are not resizes ([SCROLLTRIGGER.md](SCROLLTRIGGER.md#timelines-one-trigger-on-top), https://gsap.com/docs/v3/Plugins/ScrollTrigger/).417. **Read reduced motion through `gsap.matchMedia()`, and reduce rather than remove.** GreenSock says "Use `duration: 0` or skip the animation"; ui-animation says movement becomes short fades and state changes stay. Keep ui-animation's rule ([CORE.md](CORE.md#responsive-and-reduced-motion-with-gsapmatchmedia)).428. **One tween per value that keeps changing.** `gsap.quickTo()` for pointer followers; `overwrite: "auto"` when an enter and a leave tween fight over the same properties [GreenSock, gsap-performance], [GreenSock, gsap-core].4344## Prove it4546Search the code for `cubic-bezier(` inside GSAP vars, `scrollTrigger` on a timeline's child tween, `unitize(` with a number, and `gsap.registerPlugin` inside a component body: none remain. Mount and unmount every animated component ten times: nothing keeps running and nothing animates another instance. Hover, open and close twice fast mid-animation: it retargets without fighting. Toggle reduced motion with the page open: movement becomes short fades. Record at 4x CPU slowdown: no dropped frames. Then every file's own Prove it checks pass for the parts you touched.