Both Lottie and Framer Motion are popular animation tools for web apps, but they solve completely different problems. Using the wrong one will make your life harder. Here's how to pick.
The Core Difference
Lottie plays pre-built animations exported from a design tool (After Effects, Lottie Editor, etc.). The motion is defined entirely by the designer.
Framer Motion is a React animation library for animating DOM elements in code. The motion is defined entirely by the developer.
This isn't a competition — they're for different jobs.
When to Use Lottie
Use Lottie when:
- The animation was created in After Effects, LottieFiles Editor, or similar
- You need complex illustrated motion (characters, particles, morphing shapes)
- The animation has a fixed, pre-designed visual style that must be pixel-perfect
- You need micro-interactions from an icon library (animated icons, loading states)
- File size is critical (convert to
.lottiefor 75% smaller — verify at IconKing)
Best use cases:
- Hero animations and brand illustrations
- Animated onboarding flows
- Loading spinners and success animations
- Animated icon sets
- Complex path animations
When to Use Framer Motion
Use Framer Motion when:
- You need to animate React components based on state changes
- You need layout animations (elements moving position when others appear/disappear)
- You need gesture-based animations (drag, hover, tap)
- You need spring physics and momentum
- You need orchestrated sequences across multiple components
- You need scroll-based progress animations tied to scroll position
Best use cases:
- Page transitions
- Modal/drawer open-close animations
- Drag-and-drop interfaces
- Accordion/collapse animations
- List item add/remove animations
- Hover effects on UI components
Side-by-Side Comparison
| Feature | Lottie | Framer Motion |
|---|---|---|
| Animation source | Designer file (After Effects) | Code |
| Complexity ceiling | Very high (full AE support) | Medium (CSS-level complexity) |
| Designer control | 100% | None |
| Developer control | Limited (play/pause/speed) | 100% |
| File size | 10–200KB per animation | ~45KB library |
| Bundle impact | Per-animation | One-time overhead |
| State-driven animation | Limited | Excellent |
| Gesture support | None | Built-in |
| Layout animation | None | Built-in |
| SSR support | Needs guards | Native |
Bundle Size Reality
Lottie:
-
lottie-web: ~240KB gzipped (full build), ~150KB (light build) -
@lottiefiles/dotlottie-web: ~50KB gzipped - Per animation: 5–200KB depending on complexity (use
.lottiefor 75% reduction)
Framer Motion:
- Full bundle: ~45KB gzipped
- Motion-safe subset (
motion/react): ~17KB gzipped
If you only need a few simple loading animations, Lottie with dotLottie format can actually be lighter. If you need rich UI animations throughout your app, Framer Motion's single bundle overhead is more efficient.
Code Comparison
Loading Spinner
With Lottie:
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
// Designer created this — developer just plays it
function Spinner() {
return (
<div role="status" aria-label="Loading">
<DotLottieReact src="/animations/spinner.lottie" loop autoplay style={{ width: 48, height: 48 }} />
</div>
);
}
With Framer Motion:
import { motion } from 'framer-motion';
// Developer defines all motion in code
function Spinner() {
return (
<motion.div
role="status"
aria-label="Loading"
style={{ width: 48, height: 48, borderRadius: '50%', border: '3px solid #e0e0e0', borderTop: '3px solid blue' }}
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
/>
);
}
Modal Animation
With Lottie: You can't — Lottie doesn't animate DOM layout changes.
With Framer Motion:
import { AnimatePresence, motion } from 'framer-motion';
function Modal({ isOpen, onClose, children }) {
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ duration: 0.2 }}
style={{ position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }}
>
{children}
</motion.div>
)}
</AnimatePresence>
);
}
Animated Icon (Hover State)
With Lottie (best choice for complex icons):
import Lottie from 'lottie-react';
import { useRef } from 'react';
import heartAnim from '/animations/heart.json';
function HeartButton() {
const lottieRef = useRef(null);
return (
<button
onMouseEnter={() => lottieRef.current?.play()}
onMouseLeave={() => lottieRef.current?.stop()}
aria-label="Like"
>
<div aria-hidden="true" style={{ width: 32, height: 32 }}>
<Lottie lottieRef={lottieRef} animationData={heartAnim} loop={false} autoplay={false} />
</div>
</button>
);
}
With Framer Motion (simpler icons):
import { motion } from 'framer-motion';
function HeartButton() {
return (
<motion.button
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.9 }}
aria-label="Like"
>
<svg>/* heart SVG path */</svg>
</motion.button>
);
}
Using Both Together
The best setups often use both:
import { motion, AnimatePresence } from 'framer-motion';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
function FormSubmit({ status }) {
return (
// Framer Motion handles the container animation
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{status === 'loading' && (
// Lottie handles the complex spinner animation
<DotLottieReact src="/animations/spinner.lottie" loop autoplay style={{ width: 48, height: 48 }} />
)}
{status === 'success' && (
// Lottie plays the success animation
<DotLottieReact src="/animations/success.lottie" loop={false} autoplay style={{ width: 48, height: 48 }} />
)}
</motion.div>
);
}
Use Framer Motion for UI state transitions. Use Lottie for the illustrations inside those transitions.
Decision Tree
Is the animation a pre-built file from a designer?
├── YES → Use Lottie
└── NO → Do you need layout animation, gestures, or spring physics?
├── YES → Use Framer Motion
└── NO → Are you animating existing DOM elements?
├── YES → Use Framer Motion (or CSS transitions)
└── NO → You probably need Lottie + a designer
Quick Take
- Complex illustrated animations, brand motion, icon animations → Lottie
- UI transitions, gestures, layout animations, state-driven motion → Framer Motion
- Both → Use them together; they're complementary, not competing
Before committing to any Lottie file: preview it at IconKing — verify colors, timing, and convert to .lottie format for the smallest possible file size.
Top comments (0)