Google does. Telegram does. Duolingo does. Your product animations deserve the same treatment.
Show me whyLet's be honest. While Google, Duolingo, and Spotify are shipping buttery-smooth animations that make their apps feel alive, you're still doing this:
Your onboarding is a carousel of screenshots. Your empty states are a sad icon and some text. Your success confirmations are... nothing. Your app feels dead.
That 2MB tutorial animation? Embarrassing. Your users on mobile are watching it load frame by frame. And it still looks like pixelated garbage on a retina screen.
47 lines of cubic-bezier nonsense. Your designer hands you a beautiful After Effects comp and you spend 3 days trying to recreate it with keyframes. And god forbid they want to change it. Touch grass.
One version for iOS. Another for Android. A third for web. Maintaining three animation codebases because you didn't know there was a better way. That's insane.
Lottie is how modern apps ship world-class animations. It's a vector animation format that works everywhere—iOS, Android, web, React Native, Flutter—from a single source file. Your designer creates the animation in After Effects, exports it, and you drop it in with two lines of code. Same animation. Every platform. Pixel perfect.
And it's not just another format—it's an official industry standard. Formally recognized by IANA with an official file extension (.lot) and MIME type (video/lottie+json). The Lottie Animation Community operates under the Linux Foundation with an official v1.0 specification—and the steering committee includes Google, Airbnb, and LottieFiles. This isn't a proprietary format that could disappear tomorrow. It's backed by the companies that use Lottie at massive scale and are invested in its future.
<!-- That's it. That's the whole thing. -->
<script type="module" src="https://unpkg.com/@lottiefiles/dotlottie-wc"></script>
<dotlottie-wc src="animation.lottie" autoplay loop></dotlottie-wc>
Drop in a script tag and you're done. Or use the React, Vue, or Svelte packages if that's your thing. Either way—fucking animations in minutes, not days.
Lottie is up to 200x smaller. Your users will thank you. Your CDN bill will thank you. Just fucking use Lottie.
Because the best product teams in the world already figured this out:
Your motion designer's vision ships exactly as intended. No more "can you make it bounce a little more?" back-and-forth with developers.
Web, iOS, Android, React Native, Flutter—same animation everywhere. Your design system stays consistent across all products.
Vector-based format, not pixel garbage. Ship complex product animations without tanking your app's performance.
Build animations that respond to user actions. Hover states, tap feedback, scroll-driven motion—full interactivity, not just playback.
Respects prefers-reduced-motion. Can be paused, stopped, or hidden. Ship inclusive experiences without extra work.
Two lines of code. No build step required. Your engineering team will actually want to add animations now.
Lottie isn't just playback. These are live, interactive animations responding to your input right now:
Animation responds to your mouse
<script
src="https://unpkg.com/@lottiefiles/dotlottie-wc@0.8.11/dist/dotlottie-wc.js"
type="module"
></script>
<dotlottie-wc
id="hover-demo"
src="animation.lottie"
loop>
</dotlottie-wc>
<script>
const anim = document.getElementById('hover-demo');
anim.addEventListener('mouseenter', async () => {
const player = await anim.dotLottie;
if (player) player.play();
});
anim.addEventListener('mouseleave', async () => {
const player = await anim.dotLottie;
if (player) player.stop();
});
</script>
Animation plays on interaction
<script
src="https://unpkg.com/@lottiefiles/dotlottie-wc@0.8.11/dist/dotlottie-wc.js"
type="module"
></script>
<dotlottie-wc
id="click-demo"
src="animation.lottie">
</dotlottie-wc>
<script>
const anim = document.getElementById('click-demo');
anim.addEventListener('click', async () => {
const player = await anim.dotLottie;
if (player) {
player.stop();
player.play();
}
});
</script>
This animation follows your scroll—buttery smooth
<canvas id="scroll-canvas"></canvas>
<script type="module">
import { DotLottie } from 'https://esm.sh/@lottiefiles/dotlottie-web';
const canvas = document.getElementById('scroll-canvas');
const player = new DotLottie({
canvas,
src: 'animation.lottie',
autoplay: false,
loop: false
});
let progress = 0;
window.addEventListener('scroll', () => {
// Calculate scroll progress (0 to 1)
const scrollY = window.scrollY;
const maxScroll = document.body.scrollHeight - window.innerHeight;
progress = scrollY / maxScroll;
// Set animation frame based on scroll
if (player.isLoaded) {
const frame = Math.round(progress * (player.totalFrames - 1));
player.setFrame(frame);
}
});
</script>
Click on icons to interact with it
<script
src="https://unpkg.com/@lottiefiles/dotlottie-wc@0.8.11/dist/dotlottie-wc.js"
type="module"
></script>
<dotlottie-wc
src="animation.lottie"
stateMachineId="SM with Segments"
></dotlottie-wc>
// npm install @lottiefiles/dotlottie-web
// Or use CDN: https://esm.sh/@lottiefiles/dotlottie-web
<canvas id="canvas"></canvas>
<script type="module">
import { DotLottie } from 'https://esm.sh/@lottiefiles/dotlottie-web';
new DotLottie({
autoplay: true,
loop: true,
canvas: document.getElementById('canvas'),
src: 'https://lottie.host/animation.lottie'
});
</script>
// npm install @lottiefiles/dotlottie-react
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
const App = () => (
<DotLottieReact
src="animation.lottie"
loop
autoplay
/>
);
// npm install @lottiefiles/dotlottie-react-native
import { DotLottie } from '@lottiefiles/dotlottie-react-native';
const App = () => (
<DotLottie
source={require('./animation.lottie')}
style={{ width: 200, height: 200 }}
loop
autoplay
/>
);
<!-- npm install @lottiefiles/dotlottie-vue -->
<script setup>
import { DotLottieVue } from '@lottiefiles/dotlottie-vue'
</script>
<template>
<DotLottieVue
autoplay
loop
src="animation.lottie"
/>
</template>
<!-- npm install @lottiefiles/dotlottie-svelte -->
<script>
import { DotLottieSvelte } from '@lottiefiles/dotlottie-svelte';
</script>
<DotLottieSvelte
src="animation.lottie"
loop
autoplay
/>
// Swift Package: https://github.com/LottieFiles/dotlottie-ios
import DotLottie
struct AnimationView: View {
var body: some View {
DotLottieAnimation(
webURL: "https://lottie.host/animation.lottie",
config: AnimationConfig(autoplay: true, loop: true)
).view()
}
}
// Add to build.gradle:
// implementation 'com.lottiefiles.dotlottie:dotlottie-android:0.0.1'
import com.lottiefiles.dotlottie.core.model.Config
import com.lottiefiles.dotlottie.core.widget.DotLottieAnimation
val config = Config.Builder()
.autoplay(true)
.loop(true)
.source(DotLottieSource.Url("animation.lottie"))
.build()
dotLottieAnimationView.load(config)
// flutter pub add dotlottie_flutter
import 'package:dotlottie_flutter/dotlottie_flutter.dart';
DotLottieView(
sourceType: 'url',
source: 'https://lottie.host/animation.lottie',
autoplay: true,
loop: true,
)
dotLottie isn't the only game in town. The Lottie ecosystem has grown thanks to contributions from some big players. Here are some other open source runtimes worth knowing about:
The original. The one that started it all. Airbnb's JavaScript implementation that renders Lottie animations in the browser using SVG, Canvas, or HTML.
A C++ library for rendering vector graphics using the Lottie spec. Used in Tizen OS and other embedded systems where performance matters.
Telegram's fork of rlottie, optimized for their sticker animations. Powers billions of animated stickers sent daily.
Part of the Skia graphics library. A high-performance Lottie player used in Chrome, Android, and Flutter's rendering engine.
Each library has its trade-offs. Some prioritize performance, others compatibility. dotLottie aims for the best of both worlds with modern web standards.
Ah yes, the supposed "Lottie killer." Let's talk about what's actually true in 2025:
Rive fans love to flex their state machines. Guess what? Lottie has state machines now. Build complex, interactive animations with multiple states. Same capability, better ecosystem. And here's the kicker: Lottie has Prompt to State Machines. Just describe what you want in plain English and all the triggers, listeners, states, and transitions are done for you. No manual wiring. No node graphs. Just tell it what to do.
The dotLottie format is compressed and optimized. The file size gap that Rive used to brag about? It's gone. dotLottie delivers comparable sizes with all the benefits of the Lottie ecosystem.
The new dotLottie player is powered by ThorVG—a zero-dependency graphics engine that powers Godot and other serious rendering applications. Lottie's performance is now on par with Rive. The benchmark arguments are dead.
It's coming to Lottie. That's literally the only remaining differentiator, and it won't be for long. Meanwhile, enjoy your smaller ecosystem and pricing tiers.
Every motion designer on the planet knows After Effects. Learning Rive's editor is another skill, another tool, another license. Lottie works with what your team already uses.
LottieFiles has a massive library of ready-to-use animations. Rive's marketplace? Cute, but tiny. Need a loading spinner in 5 minutes? Lottie's got you.
Lottie is open source with many runtimes to choose from and many editors—both open source and closed source, some paid, some free. You're not locked in. Rive? One editor. One runtime. Their pricing tiers. Their roadmap. Their rules.
Lottie's been in production at Airbnb, Google, Uber, and thousands of other companies for years. The tooling is mature. The bugs are fixed. The Stack Overflow answers exist.
"So why would I ever use Rive?"
Honestly? If you're building a game engine or need data binding right now, sure. But for 99% of use cases—and 100% of cases in 6 months—just fucking use Lottie.
No you don't. Go to lottie.new and start creating with Lottie Creator right in your browser. Use Figma plugins. Or just grab one of the 500k+ free animations on LottieFiles. Someone already made what you need.
Use .lottie format instead of .json—it's compressed and optimized. dotLottie file sizes are now comparable to Rive's binary format. Still way smaller than your GIF. Still infinitely scalable. Still not pixel garbage.
Lottie respects prefers-reduced-motion. You can pause, stop, or hide animations programmatically. Add proper ARIA labels. It's more accessible than your autoplay GIF that gives people headaches.
Emails are a special hell. Use a fallback image or GIF for emails. But for web? Mobile apps? Lottie all day.
Works in Chrome, Firefox, Safari, Edge. Covers 95%+ of your users. If someone's on IE11, they have bigger problems than your animations.
This isn't just for loading spinners. The world's best apps use Lottie for their core product experiences:
Google, Airbnb, Duolingo, Spotify, TikTok, Uber—they all ship Lottie. Almost every animation you love in a modern app? Probably Lottie.
The best apps in the world use Lottie. Yours should too.
# npm
npm install @lottiefiles/dotlottie-wc
# or just use the CDN
<script src="https://unpkg.com/@lottiefiles/dotlottie-wc"></script>