EmpireUI
Get Pro
← Blog9 min read#motion#framer motion#gsap

Motion (Framer Motion) vs GSAP in 2026: Which Wins for React?

Framer Motion and GSAP both animate React apps in 2026 — but they're built for completely different jobs. Here's how to pick the right one without regretting it.

developer coding animation library comparison on dark screen

Why This Comparison Still Matters in 2026

Every couple of years someone declares this debate over, and every couple of years a new project restarts it. That's not a bad thing. Motion (the library formerly shipped as Framer Motion, rebranded to motion in v11 circa 2024) and GSAP are genuinely different tools solving genuinely different problems — and the React ecosystem has shifted enough in the last two years that answers from 2023 tutorials are now partly wrong.

Motion v11+ introduced a framework-agnostic core (motion/react for React, motion/vue for Vue, vanilla motion for everything else). GSAP 3 has been stable since 2020 but got React-specific ergonomics improvements and its ScrollTrigger plugin keeps getting refined. Neither library is standing still. So the comparison isn't "old vs new" — it's about which mental model fits your project.

In practice, most teams I've seen pick one for the wrong reason: Motion because it ships with Framer and everyone already has it installed, or GSAP because a senior dev remembers it from 2015. Neither justification is wrong, but neither is a principled decision. Let's actually compare them.

Quick aside: if you're building UI components with heavy style treatments — glassmorphism components, neobrutalism cards, aurora backgrounds — the animation library you choose will interact with your CSS setup. We'll touch on that where it matters.

Bundle Size and Setup: The First Filter

Bundle size is the bluntest filter. Motion's motion/react package weighs in around 25–34 kB gzipped for a typical feature set (as of motion v11.x). GSAP core is about 27 kB gzipped, but the moment you add ScrollTrigger, MorphSVG, or Flip you're stacking more on top — those plugins are sold separately under the Club GSAP license or bundled in specific tiers.

For a marketing site with one hero animation and a few scroll-reveal effects, neither number is a dealbreaker. But if you're building something like a design-system library that ships to dozens of consumer apps, Motion's tree-shaking story is better. You import only the hooks you use and Webpack/Rollup shakes the rest. GSAP doesn't tree-shake cleanly because its plugin system mutates the core gsap object at runtime.

Setup comparison is fast: ``bash # Motion npm install motion # GSAP (free tier) npm install gsap # GSAP Club (paid) — install from private registry npm install gsap@npm:@gsap/shockingly-good-private-pkg ` Motion works out of the box with zero config in Next.js 14+ App Router. GSAP needs a useEffect wrapper (or the newer useGSAP hook from @gsap/react`) to avoid SSR hydration mismatches. That wrapper isn't hard, but it's one more thing to get right.

Worth noting: if your project already uses Framer the design tool, you already have Motion installed — it's baked into Framer's runtime. Don't add it again as a separate dependency.

One more thing — GSAP's free tier is genuinely free for most projects. The Club GSAP tier ($150–300/yr as of 2026) unlocks plugins like DrawSVG, MorphSVG, and SplitText. If you need those, the price is fair. If you don't, the free tier is more capable than most people realise.

The React Mental Model: Declarative vs Imperative

This is the real philosophical split. Motion is declarative. You describe *what* animated state you want and React's render cycle drives the transition. GSAP is imperative. You grab a DOM ref, call gsap.to(ref.current, { ... }), and GSAP owns the timeline from that point on.

Declarative feels natural if you already think in React. Here's a Motion entrance animation that's genuinely production-ready: ``tsx import { motion } from 'motion/react'; export function FadeCard({ children }: { children: React.ReactNode }) { return ( <motion.div initial={{ opacity: 0, y: 24 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -16 }} transition={{ duration: 0.4, ease: 'easeOut' }} className="rounded-2xl bg-white/10 backdrop-blur-md border border-white/20 p-6" > {children} </motion.div> ); } ` Notice you don't manage any refs. AnimatePresence` handles exit animations when the component unmounts — something that's genuinely painful to get right with raw CSS transitions or even GSAP without extra bookkeeping.

GSAP's imperative model shines when you need *precise control* over a multi-step timeline. Imagine a product explainer: logo draws in at 0s, headline types out at 0.6s, three feature cards stagger at 1.2s, then the whole thing rewinds on scroll back up. That's a GSAP timeline in its natural habitat: ``tsx import { useRef } from 'react'; import { useGSAP } from '@gsap/react'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); export function ProductExplainer() { const container = useRef<HTMLDivElement>(null); useGSAP(() => { const tl = gsap.timeline({ scrollTrigger: { trigger: container.current, start: 'top 80%', end: 'bottom 20%', scrub: 1, }, }); tl.from('.logo', { opacity: 0, scale: 0.8, duration: 0.4 }) .from('.headline', { opacity: 0, y: 32, duration: 0.5 }, '+=0.1') .from('.feature-card', { opacity: 0, y: 48, stagger: 0.15, duration: 0.5, }); }, { scope: container }); return ( <div ref={container}> <div className="logo">...</div> <h2 className="headline">...</h2> {features.map(f => <div key={f.id} className="feature-card">...</div>)} </div> ); } ` That scrub: 1 makes the animation track the scrollbar in real time. Motion *can* do scroll-linked animations with useScroll and useTransform`, but the GSAP ScrollTrigger API is more mature for complex sequences.

Honestly, the declarative vs imperative split predicts which library you'll fight less. If you're building a component library or a SaaS dashboard, Motion's declarative API means junior devs on your team can add animations safely. If you're building a marketing microsite or a game-like experience, GSAP's timeline control is worth the added verbosity.

Performance: GPU, Layout Thrashing, and the 60 fps Question

Both libraries default to GPU-composited properties (transform, opacity) for smooth 60 fps animations. Neither one will accidentally animate width on every frame unless you tell them to. That said, they handle layout thrashing differently.

Motion's layout prop is its killer feature for reflow-heavy UI. Wrap any element with layout and Motion will calculate the element's before/after bounding box using the FLIP technique, then animate the diff with a transform — zero layout recalculation mid-animation. This makes things like accordion open/close, item reorder, or tab switching trivially smooth: ``tsx <motion.div layout className="grid gap-4"> {items.map(item => ( <motion.div key={item.id} layout initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} > {item.content} </motion.div> ))} </motion.div> ` GSAP's Flip plugin does the same thing but it's a Club GSAP feature (paid tier). If you need layout-transition animations in an open-source project, Motion's layout` prop wins by a mile.

For sheer throughput — thousands of elements animating simultaneously, canvas-level particle systems, SVG path morphs — GSAP is faster because it bypasses React's reconciliation entirely. GSAP touches the DOM directly. Motion ships a useAnimate hook that also bypasses reconciliation, but GSAP's battle-tested performance on large DOM sets is still ahead.

On mobile, both libraries respect prefers-reduced-motion. Motion does it automatically through its useReducedMotion hook if you wire it up. GSAP requires a manual check at the top of your effect. Neither does it for free without you thinking about it — so don't forget.

Worth noting: on Empire UI's, all style-hub pages — including the glassmorphism generator and the gradient tools — use Motion for UI micro-interactions precisely because layout animations on filter panels feel effortless. For anything requiring scroll-sequenced storytelling we'd reach for GSAP without hesitation.

Ecosystem, Docs, and Licensing in 2026

Motion's documentation improved significantly after the v11 rebranding. The API reference is clean, the examples are copy-paste-friendly, and the migration guide from the old framer-motion package is thorough. Community resources on YouTube and Discord are abundant. The library is MIT licensed, full stop.

GSAP's docs have always been excellent — the GreenSock team writes them with the same precision they apply to the code. The community forum is active and the codepen examples (especially for ScrollTrigger) are invaluable for visual learners. The licensing split does trip people up: GSAP core is free but Club GSAP plugins require a paid license *and* can't be used in open-source projects distributed on npm without specific arrangements. Read the license before you ship a public component library using DrawSVG.

Tool integration is worth a sentence each. Motion has first-class integration with React Server Components in Next.js 15+ — you can't use Motion hooks in a Server Component but the bundler handles the tree-shaking so your RSC bundles stay small. GSAP has no RSC opinion; it just needs to run client-side, which you enforce with 'use client' as usual.

Look, the licensing thing is what it is. For a client project or a SaaS product, GSAP Club is a cheap line item that buys you genuinely powerful plugins. For open-source UI libraries or anything where contributors might redistribute the code, Motion is the safe pick because you'll never get a license compliance question in a GitHub issue.

Which One Should You Actually Pick?

The honest answer is that most React projects don't need to choose — the scenarios where you'd regret picking the wrong one are narrower than the internet debates suggest. That said, here's a decision rule that actually holds up in practice: Pick Motion if: - You're building a component library, SaaS dashboard, or app with lots of list/tab/modal transitions - You want layout animations (layout prop) without paying for GSAP Flip - Your team is React-first and wants animations to live inside JSX declaratively - You need SSR/RSC compatibility with minimal ceremony Pick GSAP if: - You're building a marketing site, interactive story, or scroll-driven product demo - You need ScrollTrigger's scrub, pin, and snap features at their full power - You need SVG path morphing, DrawSVG, or SplitText - Performance on large DOM sets (200+ animated nodes) is a hard requirement

There's also a "both" answer that's not cheating. Using Motion for in-app UI (modal entrances, toast notifications, page transitions) and GSAP for a hero scroll section on a landing page is a totally reasonable split. They don't conflict — Motion touches React-managed DOM, GSAP touches whatever ref you hand it.

One pattern that works well in Next.js: wrap your Motion providers at the layout level for app-wide page transitions, and lazy-load your GSAP scroll sections with next/dynamic so the GSAP bundle only loads on the routes that need it. Your Lighthouse score will thank you.

If you're building with Empire UI components, the browse components page gives you a sense of which animation style each component uses. Most of our micro-interactions (hover states, toggle switches, accordion panels) are Motion-based. Our marketing templates use GSAP for scroll reveals. You're welcome to swap either — the animation logic isn't locked inside the component API.

Quick Code Cheatsheet: Side-by-Side

Sometimes you just need to see the two APIs next to each other. Here are the four most common animation patterns in both libraries: ``tsx // ---- ENTRANCE ANIMATION ---- // Motion <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.3 }}> Hello </motion.div> // GSAP useGSAP(() => { gsap.from(ref.current, { opacity: 0, duration: 0.3 }); }, { scope: ref }); ` `tsx // ---- STAGGER CHILDREN ---- // Motion const container = { hidden: {}, show: { transition: { staggerChildren: 0.1 } }, }; const item = { hidden: { opacity: 0, y: 16 }, show: { opacity: 1, y: 0 } }; <motion.ul variants={container} initial="hidden" animate="show"> {items.map(i => <motion.li key={i.id} variants={item}>{i.label}</motion.li>)} </motion.ul> // GSAP useGSAP(() => { gsap.from('.list-item', { opacity: 0, y: 16, stagger: 0.1 }); }); ` `tsx // ---- SCROLL-LINKED ---- // Motion const { scrollYProgress } = useScroll({ target: ref }); const scale = useTransform(scrollYProgress, [0, 1], [0.8, 1]); <motion.div ref={ref} style={{ scale }} /> // GSAP (more control) gsap.to(ref.current, { scale: 1, scrollTrigger: { trigger: ref.current, start: 'top 80%', scrub: true }, }); ` `tsx // ---- EXIT ANIMATION ---- // Motion (automatic with AnimatePresence) <AnimatePresence> {isOpen && ( <motion.div exit={{ opacity: 0, scale: 0.95 }} transition={{ duration: 0.2 }}> Modal content </motion.div> )} </AnimatePresence> // GSAP (manual, you handle unmount timing yourself) useGSAP(() => { if (!isOpen) { gsap.to(ref.current, { opacity: 0, scale: 0.95, duration: 0.2, onComplete: onClose, // then remove from DOM }); } }); ``

The exit animation example is the most telling. Motion's AnimatePresence handles the unmount timing automatically — you'd need to build that yourself with GSAP, delaying the React state update until the animation completes. It's doable, but it's boilerplate you'll repeat across every modal, drawer, and toast in your app.

For scroll-linked parallax at scale, that GSAP snippet with scrub: true gives you buttery-smooth timeline scrubbing that Motion's useTransform can match for simple cases but falls behind on when you stack 8+ animated elements on a single scroll trigger.

FAQ

Can I use Motion and GSAP in the same React project?

Yes, and it's actually a reasonable pattern. Motion for component-level UI (modals, lists, page transitions) and GSAP for scroll-driven sections. They don't share any global state so there's no conflict — just two extra entries in your bundle.

Is Framer Motion the same as Motion in 2026?

They're the same library. The package was rebranded from framer-motion to motion starting with v11 in 2024. The React-specific import is now motion/react. Old framer-motion imports still work via a compatibility shim but you should migrate to the new package name.

Do I need to pay for GSAP to use it in a commercial project?

GSAP core (tweens, timelines, basic eases) is free for commercial use. You only need a Club GSAP license for premium plugins like ScrollTrigger's advanced features, DrawSVG, MorphSVG, SplitText, and Flip. The free tier covers a surprising amount — check the GSAP site for the current plugin breakdown.

Which library is better for performance on mobile?

Both default to GPU-composited properties and both are fine on modern mid-range devices. GSAP edges ahead when you're animating 200+ DOM nodes simultaneously. For typical UI (cards, modals, lists under 50 items), Motion's performance is indistinguishable from GSAP's and the layout prop avoids costly reflows that you'd have to handle manually in GSAP.

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

Framer Motion vs GSAP in 2026: Honest Comparison for Real ProjectsBest CSS Animation Libraries in 2026: Motion, GSAP, Auto-AnimateMotion for React (Framer Motion) in 2026: layout, AnimatePresence, GesturesScroll Reveal Animation in React: AOS vs Framer Motion vs Intersection Observer