Chapter 9

Design-Tool Formats: Lottie & Rive

Baked playback vs state machines vs data binding.

lottie-web@rive-app/canvasstate machines
Lottie plays exported JSON; Rive runs state machines with data binding. Rive files are typically 10–15× smaller. Choose by interactivity, not just size.

The first eight chapters animated the DOM ourselves. Here the animation is authored in a design tool and shipped as a file the runtime plays back. Two formats own this space — Lottie and Rive — and the real choice between them isn't "interactive vs static." It's playback vs systems.

Two philosophies

Lottie is a JSON description of a timeline. An animator builds it in After Effects (exported with Bodymovin) or in Lottie Creator, and a player such as lottie-web walks that timeline frame by frame. Interactivity, historically, means controlling playback: which segment plays, how fast, which direction. (dotLottie added runtime State Machines in late 2025, narrowing the gap.)

Rive ships a binary .riv driven by a single C++ runtime with GPU rendering. Its differentiator is the state machine: named inputs (booleans, numbers, triggers) flow into states with transitions between them, and data binding (View Models, April 2025) wires those to your app's state. The file doesn't just play — it responds.

Demo 1 — Lottie: playback control

This circle is a hand-authored bodymovin JSON (scale + rotate keyframes), rendered by lottie-web from an inline animationData object — no network. The controls below are Lottie's whole interactivity story: play/pause, setSpeed, setDirection, playSegments, goToAndStop.

lottie-web playback live demo
loading lottie-web…
JSON size 924 bytes the entire animation, as text

Demo 2 — Rive: the state-machine model

Rive's power is hard to feel without a .riv asset, and we ship none here. So this is a state-machine concept demo — simulated in plain Svelte/Canvas: the same building blocks Rive's editor produces. Two inputs (a boolean Power and a number Charge) drive four states through transitions. Toggle and drag, and watch the active node in the graph move.

state-machine concept demo (simulated — real Rive loads a .riv) live demo
state: Idle · asleep
hover + click the orb (click = Power toggle)
INPUTS
STATE GRAPH
Idle
Hover
Active
Overload
!Power → Idle
Charge ≥ 90 → Overload
hover → Hover
else → Active

Choosing between them

The decision matrix. Read the last row first — it's the one that usually decides.

Lottie
Rive
Format
JSON (text) — .json / .lottie (zipped)
Binary .riv
Runtime model
Plays a baked, pre-rendered timeline
Runs a live state machine + data binding
Interactivity
Playback control (segments, speed, direction); State Machines via dotLottie (late 2025)
Native: inputs → states → transitions; View Models (Apr 2025)
Rendering
SVG / Canvas / HTML via lottie-web
Unified C++ runtime, GPU (Rive Renderer)
File size
Larger (verbose JSON)
Smaller (vendor: 10–15× for equivalent art)
Editor
After Effects + Bodymovin, or Lottie Creator
Rive editor (closed-source)
Openness
Open format; lottie-web open (MIT)
Runtimes open; editor proprietary
Best for
Decorative loops, micro-interactions, illustrations
Data-bound interactive components, characters, games

Playground — author a Lottie by hand

lottie-web is loaded from esm.sh. The animation is a tiny inline bodymovin object — edit the keyframe k arrays (opacity, rotation), tweak setSpeed, or uncomment setDirection / playSegments to feel the playback model directly. The byte readout prints below the box.