# GSAP vs Anime.js vs Motion Compared

> A practical comparison of GSAP, Anime.js, and Motion. Same animations built in each library, with bundle sizes, features, and a decision framework.

Published 2026-03-08 by Jake. Canonical: https://gsapvault.com/blog/gsap-vs-animejs-vs-motion

---
"Which JavaScript animation library should I use?" is one of the most frequently asked questions in frontend development. GSAP, Anime.js, and Motion are the three most popular answers, and all three are legitimate choices.

This guide compares them side by side with real code, honest trade-offs, and a decision framework to help you pick the right one for your project. No winner declared. Just the facts you need.

## The contenders

**GSAP** is the veteran. It's been battle-tested across millions of sites, with roots going back to the Flash era. GSAP offers a comprehensive plugin ecosystem (ScrollTrigger, SplitText, MorphSVG, Draggable, Flip, and more) and handles edge cases that other libraries often overlook. The core weighs in at roughly 60kb minified.

**Anime.js** is lightweight and approachable. It provides a clean API for animating DOM elements, SVG, and CSS properties with minimal overhead. Version 4 shipped in 2024 with a rewritten core. The bundle is roughly 17kb minified.

**Motion** (formerly Motion One, from the creator of Framer Motion) is the modern newcomer. Built on the Web Animations API, it takes a browser-native approach to animation. It also provides `motion/react` for declarative React animations. The core is roughly 18kb minified.

## The same animation, three ways

A staggered card entrance is a common animation pattern. Here's how each library handles it.

**GSAP:**

```javascript
gsap.from(".card", {
  y: 40,
  opacity: 0,
  duration: 0.6,
  stagger: 0.1,
  ease: "power2.out"
});
```

**Anime.js:**

```javascript
anime({
  targets: '.card',
  translateY: [40, 0],
  opacity: [0, 1],
  duration: 600,
  delay: anime.stagger(100),
  easing: 'easeOutQuad'
});
```

**Motion:**

```javascript
import { animate, stagger } from "motion";

animate(".card",
  { y: [40, 0], opacity: [0, 1] },
  { duration: 0.6, delay: stagger(0.1), easing: "ease-out" }
);
```

All three handle this cleanly. The APIs are different, but the result is identical: cards sliding up and fading in with a staggered delay. The differences show up when things get more complex.

## Where they diverge

### Scroll-linked animations

Scroll is where the gap between these libraries becomes most visible.

**GSAP** offers ScrollTrigger, which handles trigger-based animations, scroll-linked scrubbing, pinning, snapping, and callbacks. It's a mature, full-featured scroll animation system:

```javascript
gsap.registerPlugin(ScrollTrigger);

gsap.to(".progress-bar", {
  width: "100%",
  ease: "none",
  scrollTrigger: {
    trigger: ".content",
    start: "top top",
    end: "bottom bottom",
    scrub: true,
    pin: true,
    snap: 1 / 5
  }
});
```

**Anime.js** has no built-in scroll support. You'd need to combine it with the Intersection Observer API or a third-party scroll library. That's a deliberate design choice to keep the library focused, but it means extra work for scroll-heavy projects.

**Motion** includes `scroll()` and `inView()` functions that cover basic scroll-triggered and scroll-linked animations:

```javascript
import { scroll, animate } from "motion";

scroll(
  animate(".progress-bar", { width: "100%" }),
  { target: document.querySelector(".content") }
);
```

Motion's scroll API handles the fundamentals well. It doesn't offer pinning, snapping, or the depth of callbacks that ScrollTrigger provides, but it covers the most common scroll animation patterns.

### Timeline sequencing

Timelines let you coordinate multiple animations with precise control.

**GSAP** timelines are the most flexible. They support labels, position parameters, nested timelines, and full playback control (play, pause, reverse, seek, speed):

```javascript
const tl = gsap.timeline({ paused: true });

tl.to(".overlay", { opacity: 1, duration: 0.3 })
  .from(".modal", { y: 30, duration: 0.4 }, "-=0.1")
  .from(".modal-content > *", { opacity: 0, y: 10, stagger: 0.05 });

// Full playback control
openBtn.addEventListener("click", () => tl.play());
closeBtn.addEventListener("click", () => tl.reverse());
```

**Anime.js** has a timeline API with offset-based sequencing:

```javascript
const tl = anime.timeline({ easing: 'easeOutQuad' });

tl.add({ targets: '.overlay', opacity: 1, duration: 300 })
  .add({ targets: '.modal', translateY: [30, 0], duration: 400 }, '-=100')
  .add({ targets: '.modal-content > *', opacity: [0, 1], delay: anime.stagger(50) });
```

Anime.js timelines are functional for sequencing. They support play, pause, and reverse, but lack GSAP's labels, nested timelines, and position parameter flexibility.

**Motion** has a timeline function that uses an array-based syntax:

```javascript
import { timeline } from "motion";

const sequence = timeline([
  [".overlay", { opacity: 1 }, { duration: 0.3 }],
  [".modal", { y: [30, 0] }, { duration: 0.4, at: "-0.1" }],
  [".modal-content > *", { opacity: [0, 1] }, { delay: stagger(0.05) }]
]);
```

Motion's timeline API is clean and works for linear sequences. It doesn't provide the same level of runtime playback control as GSAP.

### Plugin ecosystem

**GSAP** has the largest plugin ecosystem of the three. SplitText for per-character/word/line text animation, MorphSVG for shape morphing, Draggable for drag interactions, Flip for layout animations, DrawSVG for stroke animation, Physics2D for velocity-based motion, and ScrollSmoother for smooth scrolling. All plugins are now free on CDN.

**Anime.js** includes built-in SVG path animation and staggering utilities. It deliberately avoids a plugin system to stay minimal.

**Motion** offers layout animations inherited from its Framer Motion lineage, plus the `inView` and `scroll` utilities. The ecosystem is growing but still smaller than GSAP's.

### Framework integration

**GSAP** is framework-agnostic. It works with vanilla JS, React, Vue, Svelte, Angular, and any other framework. For React, GSAP provides the `useGSAP` hook to handle cleanup:

```javascript
import { useGSAP } from "@gsap/react";

function Component() {
  const container = useRef();

  useGSAP(() => {
    gsap.from(".card", { y: 40, opacity: 0, stagger: 0.1 });
  }, { scope: container });

  return <div ref={container}>...</div>;
}
```

**Anime.js** is also framework-agnostic. It works anywhere, but you'll need to handle lifecycle cleanup manually in component frameworks.

**Motion** has the strongest React story. The `motion/react` package (the successor to Framer Motion) provides declarative animation components that feel native to React:

```jsx
import { motion } from "motion/react";

function Card() {
  return (
    <motion.div
      initial={{ y: 40, opacity: 0 }}
      animate={{ y: 0, opacity: 1 }}
      transition={{ duration: 0.6 }}
    />
  );
}
```

If your project is React-based and you want animations that integrate with component state and mounting/unmounting, Motion is purpose-built for that workflow.

## Bundle size and performance

Here are the realistic numbers:

| Library | Minified | Gzipped |
|---------|----------|---------|
| GSAP core | ~60kb | ~25kb |
| GSAP + ScrollTrigger | ~85kb | ~34kb |
| Anime.js v4 | ~17kb | ~7kb |
| Motion core | ~18kb | ~6kb |

Bundle size matters less than people think for animation libraries. A single hero image often weighs more than the difference between these libraries. Runtime performance, specifically the ability to maintain 60fps consistently, matters more than load size.

All three animate transforms and opacity efficiently. GSAP has historically done the most work on edge cases: mobile Safari quirks, SVG rendering inconsistencies, `will-change` management, and avoiding layout thrashing. That work doesn't show up in benchmarks, but it shows up in fewer bug reports on production sites.

### Accessibility

Whichever library you choose, respect the user's motion preferences:

```javascript
// GSAP
gsap.matchMedia().add("(prefers-reduced-motion: reduce)", () => {
  gsap.globalTimeline.timeScale(0);
});

// Anime.js
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
  // Skip or simplify animations
}

// Motion
import { animate } from "motion";

const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
animate(".card",
  { opacity: [0, 1] },
  { duration: prefersReduced ? 0 : 0.6 }
);
```

None of these libraries automatically disable animations for users who prefer reduced motion. That's your responsibility regardless of which library you pick.

## The decision framework

**Choose GSAP when:**
- You need scroll-linked animations with pinning, scrubbing, or snapping
- Complex timelines require play/pause/reverse control
- You need plugins like SplitText, MorphSVG, Draggable, or Flip
- Cross-browser consistency on production sites is critical
- You're working with WordPress, Webflow, or vanilla JS projects

**Choose Anime.js when:**
- Bundle size is a strict constraint
- You need clean DOM and SVG animations without scroll integration
- You want a minimal API with no plugins to learn
- Your animations are primarily entrance effects and transitions

**Choose Motion when:**
- You're in React and want declarative animation components
- Layout animations (shared element transitions) are a priority
- You prefer the Web Animations API as the underlying engine
- You want an API designed for component-based frameworks

**The honest take:** all three can handle most animation needs. The choice comes down to ecosystem fit and project requirements, not raw capability. If you need scroll-linked animations or rich plugins, GSAP is hard to beat. If you want the smallest bundle for simple effects, Anime.js or Motion work well. If you're in React and want declarative animations, Motion is purpose-built for that.

## Getting started

Each library has a low barrier to entry.

**GSAP (CDN):**

```html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/ScrollTrigger.min.js"></script>
```

**Anime.js (npm):**

```bash
npm install animejs
```

```javascript
import anime from 'animejs';
```

**Motion (npm):**

```bash
npm install motion
```

```javascript
import { animate } from "motion";
```

All three have solid documentation. [GSAP's docs](https://gsap.com/docs) are particularly thorough, with interactive examples for every method. Anime.js and Motion both provide clear API references and getting-started guides.

## Conclusion

There's no universal "best" animation library. GSAP, Anime.js, and Motion each solve different problems well.

GSAP gives you the deepest toolkit: scroll integration, timeline control, a rich plugin ecosystem, and years of production-hardened edge case handling. Anime.js gives you a lightweight, focused animation API without the overhead of features you might not need. Motion gives you a modern, framework-friendly approach built on browser-native APIs, with first-class React support.

The best animation library is the one that fits your project's needs. Understand what you're building, check the requirements against each library's strengths, and pick accordingly. You can always add a different tool later if your needs change.

---

*Looking for production-ready GSAP effects? Browse the [GSAP Vault effects library](/effects) for scroll animations, text effects, and interactive components you can drop into any project.*

## Related articles

- **[GSAP vs CSS Animations: A Practical Guide](/blog/gsap-vs-css-animations)** - When should you use CSS animations versus GSAP? A practical look at the trade-offs.
- **[Animate on Scroll: 3 Approaches Compared](/blog/how-to-animate-on-scroll)** - CSS scroll animations, Intersection Observer, and GSAP ScrollTrigger compared hands-on.
- **[Using AI to Customize GSAP Effects](/blog/using-ai-assistants-gsap-effects)** - How to use AI assistants to adapt and customize GSAP animation code.