Comparisons
CSS animation vs Lottie: file size, performance and when to use each
CSS animation or Lottie? A neutral comparison of file size, performance, interactivity and tooling, with code for both and a simple rule for picking one.
CSS animation and Lottie are both common ways to add motion to a web page, but they solve different problems. CSS animates the elements you already have: buttons, cards, menus. Lottie plays an animation that a designer made in another tool, usually After Effects, exported as JSON. Picking the wrong one costs you either file size, performance or a lot of hand-tuning.
This post compares the two on the things that decide the choice in practice: file size, performance, interactivity, tooling and who maintains it.
What each one is
CSS animation
CSS gives you two built-in ways to animate: transitions, which move a property from one value to another when a state changes, and keyframe animations, which run a sequence defined with @keyframes. Both use an easing function and a duration. No library is needed. The browser handles everything.
.badge {
animation: pop-in 420ms cubic-bezier(.34, 1.56, .64, 1) both;
}
@keyframes pop-in {
from { opacity: 0; transform: scale(.6); }
to { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
.badge { animation: none; }
}
Lottie
Lottie is a JSON format for vector animation. A designer animates in After Effects, exports with the Bodymovin plugin or a similar tool, and you get a .json file (or a zipped .lottie file). On the web, a player library such as lottie-web reads the file and draws each frame to SVG or canvas.
import lottie from 'lottie-web';
const anim = lottie.loadAnimation({
container: document.getElementById('hero-anim'),
renderer: 'svg',
loop: true,
autoplay: true,
path: '/animations/hero.json',
});
// later, for example when the element leaves the screen
anim.pause();
The same JSON file can also play in native iOS and Android apps with their Lottie libraries. That cross-platform reach is one of Lottie's main strengths.
Side by side
| CSS animation | Lottie | |
|---|---|---|
| What it animates | Your existing HTML elements | A separate vector animation inside a container |
| Extra download | None, beyond a few lines of CSS | The player library plus the JSON file |
| Rendering | Browser engine; transform and opacity can run on the compositor | JavaScript draws SVG or canvas each frame |
| Interactivity | Hover, focus, active, checked and classes built in | Through the player API: play, pause, seek, segments |
| Authoring | Code, or tools that export CSS | After Effects or other tools that export Lottie |
| Complex illustration | Hard: morphs, masks and many layers get messy | Strong: built for it |
| Platforms | Web | Web, iOS, Android and more |
| Theming | Uses your CSS variables and styles directly | Colors live in the JSON unless you change them in code |
File size
A CSS animation adds almost nothing to the page. The keyframes above are a few hundred bytes, and they reuse elements that are already there.
Lottie has two costs. The first is the player. lottie-web is tens of kilobytes even when compressed, and you load it before anything plays. Lighter builds and other players exist, but there is always a runtime. The second is the JSON file, which grows with the number of layers, shapes and keyframes. A simple icon may be a few kilobytes. A detailed illustration exported with raster images embedded can be much larger.
Compared with a GIF or a video of the same illustration, Lottie is often smaller and stays sharp at any size. Compared with CSS for a UI state change, it is almost always larger.
Performance
Browsers can animate transform and opacity on the compositor thread. That means a CSS animation of those properties can stay smooth even when JavaScript is busy. Animating layout properties like width or top is slower, because the browser has to recalculate layout each frame, so stick to transform and opacity where you can.
Lottie's web player computes every frame in JavaScript and updates SVG attributes or redraws a canvas. For one small animation this is fine. For many animations at once, long-running loops, or large files with many layers, it adds main-thread work, which can affect scrolling and input on slower devices. Good practice:
- Pause Lottie animations when they scroll out of view.
- Prefer the SVG renderer for crisp small graphics, canvas for heavy scenes, and test both.
- Keep layer counts low when exporting.
- Respect
prefers-reduced-motionby not autoplaying.
Interactivity
CSS is built around state. A hover, a focus ring, a pressed button or a checked toggle each have a selector, and transitions run automatically when the state changes. The animation lives next to the component's styles, so it stays in sync when the design changes.
Lottie is a timeline you control from JavaScript. You can play, pause, reverse, jump to a frame or play a range of frames. That works well for things like an animated checkbox that plays frames 0 to 30 on check and 30 to 60 on uncheck. It takes more wiring than a CSS transition, and the element inside is not a normal DOM element you can style with your design tokens.
Tooling and workflow
The biggest practical difference is who makes the animation.
- CSS is usually written by a developer, from a spec or a prototype. The risk is that timing and easing drift from what the designer intended. A clear motion spec with durations and curves helps. See CSS easing functions explained.
- Lottie is usually made by a motion designer and dropped in by a developer. The motion arrives exactly as designed, but changing a duration or a color usually means going back to the source file and exporting again.
When to use which
Use CSS animation when:
- You are animating UI: buttons, menus, cards, tabs, toasts, modals.
- The motion responds to hover, focus, press or other states.
- You care about the smallest bundle and the smoothest scrolling.
- The animation should pick up your theme colors and tokens.
Use Lottie when:
- The motion is an illustration: an onboarding scene, an empty state, a mascot, a detailed animated icon.
- It has shape morphs, masks or many layers that would be painful in CSS.
- A motion designer owns it in After Effects and will keep iterating.
- You need the same animation on web, iOS and Android.
Plenty of products use both: CSS for every interactive element and Lottie for a few illustrations.
Capturing either one
Whichever format a site uses, you can study it the same way. The Capture Motion Chrome extension captures CSS transitions and keyframes, the Web Animations API, GSAP and Lottie. Pick the element, play it, and you get the keyframes, durations, delays and easing of each animated property. Export it as an HTML and CSS file, a React component, JSON, a prompt for an AI coding assistant, or a Figma Motion timeline through the Figma plugin.
That is useful in both directions. If a site uses Lottie for something that should really be a light CSS animation, capture it and see whether the motion is simple enough to rebuild in CSS. If you want to know exactly how a CSS micro-interaction is timed before you recreate it, capture it instead of guessing. For the full process, read how to copy an animation from any website.
Questions
Is Lottie faster than CSS animation?
Usually not on the web. CSS animations of transform and opacity can run on the compositor, off the main thread. Lottie's web player updates SVG or canvas from JavaScript on every frame, which costs more, especially with many layers.
Is a Lottie file smaller than a GIF or video?
Often, yes, for vector illustrations. A Lottie JSON file stores shapes and keyframes, not pixels. But on the web you also load the player library, which is larger than most CSS animations.
Can I convert a Lottie animation to CSS?
Simple ones, yes: a few layers moving, scaling and fading map well to CSS keyframes. Complex shape morphs and masks do not. Capture Motion can capture a playing Lottie animation and export the motion as CSS, React or JSON.
Which is better for UI micro-interactions?
CSS in most cases. Hover, focus, press and toggle states are built into CSS, need no library, and stay in sync with your component styles. Use Lottie when the motion is an illustration rather than a UI state change.
