GSAP (GreenSock Animation Platform) is a JavaScript library for animating anything code can reach: CSS, SVG, canvas, WebGL and plain objects. Since April 30, 2025, it's been free for everyone, including every plugin, thanks to Webflow's sponsorship.
What GSAP Is
GSAP is an animation engine that works on top of any framework and in every modern browser. Instead of manually wrestling with CSS transitions and requestAnimationFrame, you describe an animation declaratively, and the library handles timing, easing and performance.
Three reasons GSAP has held the top spot on the web for over 15 years:
- Reliable behavior across browsers, including edge cases with SVG and transforms.
- Precise control over sequences via timelines.
- A plugin ecosystem covering scroll effects, morphing, text splitting and dragging.
Some plugins used to sit behind a paid Club membership. Now the entire set is open and cleared for commercial projects.
Key Features
| Feature | What it does |
|---|---|
| gsap.to() / from() / fromTo() | Basic tweens: animate properties from one value to another |
| Timeline | Assembles animations into a controllable sequence with pauses and overlaps |
| Easing | Shapes the motion: spring, bounce, smooth deceleration |
| stagger | Runs an animation across a list of elements one after another |
| gsap.matchMedia() | Different animations per breakpoint and for prefers-reduced-motion |
| ScrollTrigger | Ties an animation to scroll position: reveal, pin, parallax, scrub |
| SplitText | Splits text into lines, words and characters for animation |
| Flip | Smoothly animates the transition between two layout states |
| Draggable | Dragging, inertia, snapping to a grid |
Installation
Quick Start via CDN
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script>
gsap.to(".box", { x: 300, duration: 1, ease: "power2.out" });
</script>
Installing via npm
npm install gsap
import gsap from "gsap"
gsap.to(".box", { rotation: 360, duration: 2 })
Registering Plugins
Plugins are installed separately and registered once when the app starts:
import gsap from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"
gsap.registerPlugin(ScrollTrigger)
If a plugin's animation silently doesn't work, the first thing to check is whether you called
gsap.registerPlugin(). It's the most common cause.
React Integration
In React, animations need to start after mounting and clean up on unmount. GSAP has an official @gsap/react package with a useGSAP() hook for exactly this.
npm install gsap @gsap/react
The useGSAP Hook
useGSAP() works similarly to useEffect, but it automatically tracks every animation it creates and cleans them up when the component unmounts. You don't need to write manual cleanup code.
import { useRef } from "react"
import gsap from "gsap"
import { useGSAP } from "@gsap/react"
gsap.registerPlugin(useGSAP)
function Hero() {
const container = useRef()
useGSAP(
() => {
gsap.from(".title", { y: 40, opacity: 0, duration: 0.8, ease: "power2.out" })
gsap.from(".subtitle", { y: 20, opacity: 0, duration: 0.6, delay: 0.2 })
},
{ scope: container }
)
return (
<section ref={container}>
<h1 className="title">Title</h1>
<p className="subtitle">Subtitle</p>
</section>
)
}
Why scope Matters
The scope option limits selectors (.title, .subtitle) to the container's boundaries, so one component's animation doesn't accidentally affect same-named classes elsewhere on the page.
ScrollTrigger Inside a Component
import { useRef } from "react"
import gsap from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"
import { useGSAP } from "@gsap/react"
gsap.registerPlugin(ScrollTrigger, useGSAP)
function Features() {
const container = useRef()
useGSAP(
() => {
gsap.from(".card", {
y: 60,
opacity: 0,
stagger: 0.15,
scrollTrigger: { trigger: ".cards", start: "top 80%" },
})
},
{ scope: container }
)
return (
<div ref={container}>
<div className="cards">
<div className="card">1</div>
<div className="card">2</div>
<div className="card">3</div>
</div>
</div>
)
}
In Next.js and other SSR frameworks, keep the ScrollTrigger import and animation startup inside a client component.
useGSAPruns after mounting, so DOM access inside it is safe.
Pricing and License
As of April 30, 2025, GSAP is free for everyone, including the full set of previously paid plugins and commercial use. A separate subscription is no longer required.
One license restriction remains: GSAP can't be embedded in products that compete with Webflow's visual builder — that is, in your own no-code animation tools. There are no restrictions for regular websites, landing pages and applications.
Practical Scenarios
Revealing Blocks on Scroll
gsap.from(".section", {
y: 50,
opacity: 0,
duration: 0.8,
scrollTrigger: { trigger: ".section", start: "top 85%" },
})
Pinning a Section With Parallax
gsap.to(".bg", {
yPercent: -30,
ease: "none",
scrollTrigger: {
trigger: ".hero",
start: "top top",
end: "bottom top",
scrub: true,
pin: true,
},
})
Animating a Headline Letter by Letter
import { SplitText } from "gsap/SplitText"
gsap.registerPlugin(SplitText)
const split = new SplitText(".headline", { type: "chars" })
gsap.from(split.chars, { y: 20, opacity: 0, stagger: 0.03 })
Micro-Interactions on Buttons
const btn = document.querySelector(".cta")
btn.addEventListener("mouseenter", () => gsap.to(btn, { scale: 1.05, duration: 0.2 }))
btn.addEventListener("mouseleave", () => gsap.to(btn, { scale: 1, duration: 0.2 }))
Using It in an AI Site Builder for Landing Pages
Tools like Codex's site-building plugin can assemble, save and deploy websites, web apps and dashboards straight from a description. That's convenient for a landing page: you describe the structure and animations in words, and the agent assembles and publishes the finished page. GSAP fits neatly into that workflow — the library can usually be added with a single tag in <head>, after which the agent wires up the animations across the markup.
Practical steps:
- In your prompt, ask for GSAP and the plugins you need to be loaded via CDN.
- Describe the animations section by section, specifically: what moves, from where, with what delay.
- Ask for the animation setup to be wrapped in a
prefers-reduced-motioncheck, to respect accessibility settings. - After the page is built, check it on mobile — heavy
pinandscrubeffects are sometimes worth disabling on narrow screens viagsap.matchMedia().
Example prompt snippet:
Load GSAP and ScrollTrigger via CDN. On the landing page:
- hero: the headline and button fade in from below with a 0.2s delay;
- benefits section: cards slide in one after another once they reach 80% of the viewport;
- the hero background image moves with a parallax effect on scroll.
Wrap the animations in matchMedia: disable the parallax effect on screens narrower than 640px.
This approach gives you a lively landing page without hand-coding the animations — you describe the behavior in words, and the agent assembles the finished page.
Common Issues: What to Do If…
- A plugin's animation doesn't fire —
gsap.registerPlugin()wasn't called. - The animation is janky — you're animating
top/leftinstead ofx/y; transforms run on the GPU and are much smoother. - In React, the animation repeats or breaks on route transitions — the setup isn't wrapped in
useGSAP(), orscopeisn't set. - ScrollTrigger calculates positions incorrectly — call
ScrollTrigger.refresh()after fonts and images have loaded. - The animation gets in users' way —
prefers-reduced-motionisn't handled viagsap.matchMedia().
Further Reading
- Official site: gsap.com
- Documentation: gsap.com/docs/v3
- ScrollTrigger: gsap.com/docs/v3/Plugins/ScrollTrigger
- React package: @gsap/react
- GitHub: github.com/greensock/GSAP
