Skip to content

Web Development

Lottie vs CSS vs Rive — Picking the Right Animation Format for the Web

Lottie is the After Effects → web pipeline every animator uses. CSS keyframes powers the micro-interactions that polish a UI. Rive is interactive character animation with game-feel physics. They're not competitors — they're three different tools solving three different problems. Aidxn uses Lottie for hero illustrations (animator ships JSON, we drop it on the page), CSS for buttons and icons (pure performance), and Rive for anything interactive that needs to feel alive. Here's how to pick, what the tradeoffs are, and how to ship all three without bloat.

🎨 🎮

Animation on the web has matured. It's no longer "should we animate?" but "which animation tool gets shipped to production right now?" Three ecosystems have carved out their territory, and confusion happens because they're not alternatives — they're purpose-built for completely different moments in a user's journey.

If you're a designer in After Effects and want to ship motion to the web without learning JavaScript, Lottie is your answer. Hand the JSON file to a developer, they drop it in HTML, it plays. No code. No math. If you're building a button that needs a hover state or a loading spinner, CSS is still the right choice — it's literally 4 lines, zero JavaScript runtime, ships in your CSS bundle. If you're building a character that responds to user input (drag, click, scroll) and needs to feel alive, Rive is the only tool that feels like a video game, because it basically is one.

Aidxn ships all three. Different sections, different tools. Understanding when to reach for which one separates production sites from sites that feel polished.

Definition: What Are They?

Lottie is a framework (iOS, Android, web) that plays animations exported from After Effects as JSON. An animator creates motion in AE, exports it via the Lottie plugin (freemium), and gets a JSON file. That JSON plays on web via lottie-web library (~60kb minified + gzipped). File sizes are tiny (10–30kb for complex animations) because they're vector paths + transform math, not raster frames. Aidxn uses Lottie for hero section illustrations (animated SVG-style visuals that loop infinitely, no interaction).

CSS keyframes (plain old @keyframes, not Tailwind animations) define motion using CSS syntax. A button goes from opacity: 0 to opacity: 1. A spinner rotates 360°. These ship in your CSS file (zero runtime overhead) and run at 60fps on most devices. CSS is tiny (typically 200 bytes per micro-interaction), requires zero JavaScript, and performs better on mobile than JavaScript-driven animation at the same scale. Aidxn uses CSS for icon animations, loading spinners, and button hover states.

Rive is a design + runtime tool for interactive animation. Animators design in Rive's editor (similar to Adobe XD or Figma), then export to .riv files that play in a browser runtime (~400kb total, but heavily cached and reusable). Rive understands state machines (this character state → that character state on scroll/click), physics, and interactivity. A character can respond to mouse position, follow a drag, or trigger animation sequences based on user input. Rive files are vectorial (like Lottie) but stateful and interactive (unlike Lottie). Aidxn uses Rive for character interactions in moonshot and product demos.

The Head-to-Head Comparison

File Size: CSS wins at micro-scale (4 lines = 0 extra bytes). Lottie wins at mid-scale: a 4-second hero animation is 15–25kb. Rive costs more upfront (~100kb per unique file) but compounds favorably if you reuse the same character across multiple pages (file caches, 1 download). Don't optimize here — ship what's right for the experience.

Performance: CSS animations run on the GPU, unchecked by JavaScript. Lottie runs on the CPU but is optimized aggressively (LottieJS is 15 years old, battle-tested). Rive runs on GPU with a small runtime overhead. In practice: CSS is fastest (milliseconds to parse), Lottie is fast enough (imperceptible on desktop, 1–2% CPU on mobile), Rive is smooth (game-engine performance). Mobile testing required before shipping; desktop is a non-issue for all three.

Tooling & Authorship: CSS requires a developer. You write code. Lottie requires an animator who knows After Effects (or Figma → Lottie export plugin). Designer ships JSON, developer uses it. Rive requires an animator who switched to Rive (learning curve exists, but lower than AE). No developer hand-off needed — export .riv, drop in HTML. Lottie and Rive empower designers; CSS requires engineering.

Interactivity: CSS can't respond to user input beyond hover/focus/active pseudo-classes. Lottie can't respond to user input at all (it plays or it doesn't). Rive is built for it — mouse position, drag, scroll, clicks, all flow into the animation state machine. If you need interactivity, CSS is limited (micro-interactions only), Lottie is not an option, Rive is the only choice. But if you don't need interactivity, Rive is overkill.

Three Use Cases That Define the Boundary

Use Case 1: Hero Illustration (Lottie)

Your homepage needs a 3–4 second looping animation of a character or object. It's an illustration, not interactive. An animator creates it in After Effects, exports JSON via the Lottie plugin. You drop it on the page:

import { DotLottieReact } from '@lottiefiles/dotlottie-react';

export const HeroAnimation = () => {
  return (
    <div className="w-full h-96 flex items-center justify-center">
      <DotLottieReact
        src="/animations/hero-wave.json"
        loop
        autoplay
        speed={0.8}
        className="w-full h-full"
      />
    </div>
  );
};

The JSON file is 18kb. The lottie-web library is 60kb, shared across your site (loaded once). The animation plays smoothly, pixel-perfect because it exported from AE. No developer created the motion — the animator did, in the tool they already know. This is Lottie's superpower: designer → motion → web, with zero JavaScript authorship in the middle. Aidxn uses Lottie for brand illustrations in <HeroStatic> sections and background SVG loops.

Use Case 2: Loading Spinner (CSS)

Your form is submitting. Show a spinner for 2 seconds. It's pure CSS:

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.loading-spinner {
  width: 24px;
  height: 24px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

4 lines of code (plus defaults). No JavaScript. Ships in your CSS file. Runs at 60fps on any device, including 2-year-old Android phones. Zero runtime overhead. If you ship a Lottie JSON just for a spinner, you're paying 60kb for 20 bytes of motion. CSS wins. Aidxn uses CSS for spinners, skeleton screens, and hover effects on buttons and links.

Use Case 3: Interactive Character (Rive)

Your product page has a mascot character. Move your mouse, the character's eyes follow. Scroll down, the character reacts. Click a button, the character plays a celebration animation. This needs state machine logic — something that responds to user input and decides "what state am I in now?" CSS can't do this. Lottie can't do this. Rive was built for this:

import { Rive } from '@rive-app/canvas-advanced-js';

export const InteractiveCharacter = () => {
  const riveRef = useRef(null);
  const containerRef = useRef(null);

  useEffect(() => {
    const rive = new Rive({
      src: '/characters/mascot.riv',
      canvas: riveRef.current,
      autoplay: true,
      onLoad: () => {
        // Trigger state on scroll
        window.addEventListener('scroll', () => {
          const state = rive.stateMachineInputs(0);
          const scrollPercent = window.scrollY / document.body.scrollHeight;
          state[0].value = scrollPercent; // Pass scroll to animation state
        });
      }
    });

    return () => rive.cleanup?.();
  }, []);

  return <canvas ref={riveRef} className="w-full max-w-2xl" />;
};

The .riv file (~80kb) contains a state machine: idle, reacting, celebrating, sleeping. JavaScript feeds scroll position into the state machine. Rive decides which animation plays, at what speed, with what physics. It feels alive because it's responding in real-time. This is impossible to build with CSS (state-agnostic) or Lottie (plays linearly, no branching). Aidxn uses Rive for interactive product walkthroughs and character-driven feature demos.

Real Code: Aidxn's Tri-Stack

A typical Aidxn marketing page stacks all three:

// HeroSection.astro
<section>
  <HeroAnimation /> {/* Lottie: 18kb animation */}
  <h1 className="animate-fade-in">{/* CSS: fade-in keyframe */}
    Build Motion That Converts
  </h1>
  <button className="hover:scale-105 transition-transform">
    {/* CSS: hover scale */}
    Learn More
  </button>
</section>

// FeatureSection.astro
<section>
  <InteractiveCharacter /> {/* Rive: 80kb state machine */}
  <p>Scroll down to see the character react</p>
</section>

// LoadingOverlay.astro
<div className="fixed inset-0 bg-black/50">
  <div className="absolute inset-0 flex items-center justify-center">
    <div className="loading-spinner"> {/* CSS: 0 bytes, in stylesheet */}
</div>
</div>

Total animation budget across the page: Lottie 60kb (once) + Rive 400kb (once) + CSS in stylesheet. Three tools, three purposes, zero conflicting approaches.

Six FAQs

Should I use Lottie or Rive for a character animation?

Lottie if it doesn't move based on user input (hero, background loop, loading state). Rive if it responds to scroll, mouse, or clicks. Lottie is "play this video," Rive is "this character has AI." Different tools.

Can Rive replace CSS animations?

Technically yes, but no. A button hover effect in Rive is 80kb+ overhead. In CSS it's 50 bytes. Ship CSS for micro-interactions. Reserve Rive for complex, interactive experiences where the overhead is justified.

Is 60kb of Lottie too much for a single animation?

Only on your first animation per page. After that, it's cached and shared. If you ship 3 Lottie animations on one page, the second and third cost 20kb each (just the JSON files). The library loads once. Don't optimize prematurely — profile it.

Can I export from Figma to Lottie?

Yes, via third-party plugins (Figma → Rive is cleaner). But After Effects → Lottie is the native workflow. If you're designing in Figma, consider Rive instead (design → export .riv, done). For AE workflows, use Lottie.

Do I need to learn Rive if I want interactive animation?

If you have a designer/animator on your team, yes — they learn Rive (4–6 hours), export .riv, and hand it off. If you're a solo developer, CSS + JavaScript state handlers might be faster than learning a new tool. Profile the ROI per project.

Which one is best for mobile?

CSS is safest (native, no runtime). Lottie and Rive both work but require testing. The LottieJS runtime is optimized for mobile, and Rive's canvas renderer is smooth. Profile on real devices. Target 60fps. If you can't hit it, dial back complexity or strip animations entirely — a fast no-animation page beats a janky animated page.

The Bottom Line

Animation format choice is a production decision, not a technology preference. CSS keyframes win on simplicity, performance, and file size for micro-interactions. Lottie wins on designer-to-web pipeline (animator ships motion, developer pastes JSON). Rive wins on interactivity and game-feel where the extra file size is justified by the experience uplift.

The sites that convert use all three. A homepage uses Lottie for the hero because the animator owns that motion. Buttons animate on CSS hover because there's no need for overhead. A product walkthrough uses Rive because the character needs to respond to scroll and feel alive. Each tool does one job, done well.

Start by profiling: what's the interaction model? No interaction? Lottie or CSS. Real-time response to user input? Rive. Hover states and spinners? CSS. If you're shipping motion for a customer site, reach out — we own all three pipelines and can advise on which to ship. For deeper motion engineering patterns, check out our post on Framer Motion vs GSAP animation orchestration, which covers how to compose these tools with JavaScript-driven animation for full-page experiences.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.