Jun 8, 20269 min read/2026/06/08/lottie-small-animations-that-make-software-feel-alive/

Lottie: Small Animations That Make Software Feel Alive

Lottie: Small Animations That Make Software Feel Alive

After writing about Remotion, I kept thinking about the smaller end of the motion spectrum.

Remotion is excellent when I want to generate a real video: a reel, a product demo, a release-note clip, a customer-specific walkthrough. But not every motion problem deserves a video pipeline.

Sometimes I do not want a video at all.

Sometimes I just want the application to answer back.

Sometimes the right answer is much smaller:

  • a success checkmark after saving a form
  • an empty-state illustration that breathes a little
  • a loading animation that matches the brand
  • a feature card that explains itself in three seconds
  • a tiny onboarding animation that runs inside the product
  • an icon that reacts when the user clicks it

That is where Lottie fits. It is not the big cinematic part of the story. It is the little part that happens after the user clicks the button, opens the panel, finishes the import, or lands on an empty screen.

The mental model

A Lottie file is not a GIF and it is not a video. It is a JSON description of a vector
animation
: shapes, layers, transforms, timing, keyframes, easing, masks, and assets. A Lottie
player reads that JSON and renders the animation at runtime.

That means a Lottie animation behaves more like an animated SVG than a video clip:

  • it stays sharp at different sizes
  • it can be much smaller than raster video for simple motion
  • it can be looped, paused, scrubbed, and triggered
  • it can be used in web, mobile, and desktop apps
  • it can be versioned and shipped as an app asset

The simplest way I think about it is this:

Remotion is for producing video files. Lottie is for putting motion inside software.

They overlap a little, but their center of gravity is different. Once I framed it like that, the difference became much easier to reason about.

Lottie JSON and dotLottie

The original format is Lottie JSON. It is plain JSON, which is nice because it is easy to inspect, diff, compress, and serve from a CDN. That also makes it feel more like an application asset than a traditional design export.

The newer packaging format is dotLottie (.lottie). A dotLottie file is a packaged
container for one or more animations plus metadata and related resources. The current
LottieFiles developer docs emphasize dotLottie players for web, React, Vue, Svelte, mobile, and
desktop, with newer capabilities like theming and state machines.

My practical rule:

  • Use Lottie JSON when you want the simplest, most transparent asset.
  • Use dotLottie when you want packaging, multiple animations, theming, or interactive
    animation behavior.

If you are just dropping a small success animation into a product, JSON is fine. If you are building a reusable animation system, dotLottie starts to look more interesting.

This is the part I like: the animation can stay in the same mental world as the rest of the app. It can be reviewed, shipped, cached, and replaced like any other asset.

The smallest web example

With the current LottieFiles web player, the basic setup is a canvas and a player instance. Nothing magical:

npm install @lottiefiles/dotlottie-web
<canvas id="status-animation" style="width: 240px; height: 240px;"></canvas>
import { DotLottie } from "@lottiefiles/dotlottie-web";

const canvas = document.querySelector<HTMLCanvasElement>("#status-animation");

const animation = new DotLottie({
  canvas,
  src: "/animations/success.lottie",
  autoplay: true,
  loop: false,
});

That is the basic shape: the asset lives outside the code, and the code decides when it plays. I like that separation. The designer owns the motion. The application owns the state.

React example

In a React app, I would usually wrap the animation behind a component so the rest of the UI does not care which player is being used:

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

export function SaveComplete() {
  return (
    <div className="save-complete">
      <DotLottieReact
        src="/animations/success.lottie"
        autoplay
        loop={false}
        style={{ width: 180, height: 180 }}
      />
      <p>Changes saved</p>
    </div>
  );
}

The component is small, but the UX difference is real. Instead of a static "Saved" message, the interface acknowledges the action with motion.

That is where Lottie shines: micro-feedback.

Three tiny Lottie examples

I added a few tiny examples here because this is easier to understand when it is moving. These are not meant to be fancy. They are the kind of animations I would actually use in a product: a one-shot save success, a looping sync indicator, and a gently moving empty state.

They are intentionally simple. The point is not to make a cinematic scene. The point is to show the kind of small product motion that Lottie is good at: clear, reusable, state-driven UI feedback.

The demo page loads three local JSON files:

/media/lottie/save-success.json
/media/lottie/syncing-dots.json
/media/lottie/empty-state.json

The loader code is small:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
<script>
  const examples = {
    "save-success": { path: "./save-success.json", loop: false },
    "syncing-dots": { path: "./syncing-dots.json", loop: true },
    "empty-state": { path: "./empty-state.json", loop: true },
  };

  for (const [id, config] of Object.entries(examples)) {
    lottie.loadAnimation({
      container: document.getElementById(id),
      renderer: "svg",
      loop: config.loop,
      autoplay: true,
      path: config.path,
    });
  }
</script>

And the JSON itself is just animation data. For example, the success check uses a circle layer
and a trimmed stroke layer:

{
  "v": "5.12.2",
  "fr": 30,
  "w": 240,
  "h": 240,
  "layers": [
    { "ty": 4, "nm": "Green circle" },
    { "ty": 4, "nm": "Check stroke" }
  ]
}

That is why Lottie is a nice bridge between design and engineering: the designer thinks in layers and keyframes, but the product ships a structured asset the application can control.

Control it like UI, not media

The mistake I see with Lottie is treating every animation as decorative autoplay. That is the fast path to annoying UI and poor mobile performance.

The better approach is to wire animation to product state:

async function saveProfile() {
  saveButton.disabled = true;
  spinner.play();

  try {
    await api.saveProfile(formData);
    spinner.stop();
    successAnimation.play();
  } catch {
    spinner.stop();
    errorAnimation.play();
  } finally {
    saveButton.disabled = false;
  }
}

The animation is not there because motion is cool. It is there because the state changed: loading, success, error, empty, complete, unlocked, connected.

That distinction matters.

Lottie and Remotion together

This is where the Remotion connection gets interesting, and it is the reason this post belongs next to the Remotion one.

If Remotion is your video assembly system, Lottie can be one of the asset types inside that
system. A designer can create a small animated badge, logo mark, transition, or icon in Lottie,
and Remotion can place it into a larger generated video.

Remotion has a Lottie package for this:

npm install @remotion/lottie --save-exact

Then the animation can be used as part of a composition:

import { Lottie } from "@remotion/lottie";
import animationData from "./success.json";

export function ProductLaunchScene() {
  return (
    <AbsoluteFill>
      <h1>Feature shipped</h1>
      <Lottie animationData={animationData} />
    </AbsoluteFill>
  );
}

That gives you a nice division of labor:

  • Lottie handles small reusable motion assets.
  • Remotion handles the full rendered video.

For a product launch reel, the checkmark, logo pulse, loading spinner, or animated chart accent could be Lottie. The final 9:16 video is still Remotion.

That feels very natural to me. Small motion assets become building blocks. Remotion becomes the assembly line.

When Lottie is the right tool

I would reach for Lottie when the animation is:

  • short
  • vector-like
  • reusable
  • brand-specific
  • part of product UI
  • controlled by app state
  • expected to stay sharp at multiple sizes

Examples:

  • save success
  • upload progress
  • empty inbox
  • onboarding steps
  • animated icons
  • feature highlights
  • small hero illustrations
  • achievement/unlock moments
  • "connecting..." or "syncing..." states

The key word is small. Lottie is fantastic for little moments of motion. When it stays in that lane, it is very hard not to like it.

When Lottie is the wrong tool

I would avoid Lottie when the animation is:

  • long
  • cinematic
  • photographic
  • full of raster images
  • full of blur, masks, and heavy effects
  • running many times in a scrolling list
  • basically a video disguised as JSON

If the animation is a 20-second story, use video. If it is a product reel, use Remotion or a normal video pipeline. If it is complex character animation with lots of effects, test carefully before assuming Lottie will be cheap.

Lottie can be lightweight, but it is not automatically lightweight. A huge JSON file with many
paths, masks, gradients, and effects can still hurt performance.

Performance notes

The boring rules are the important ones:

  • Do not autoplay dozens of animations on a page.
  • Pause animations when they are offscreen.
  • Prefer short loops.
  • Test on mobile hardware, not only on your development machine.
  • Keep the art simple: fewer layers, fewer masks, fewer effects.
  • Use the right renderer/player for the platform.
  • Treat animations as UI state, not background noise.

The newer dotLottie web player direction is especially interesting because the LottieFiles ecosystem is pushing hardware-accelerated rendering paths like WebGL and WebGPU. That does not mean you can ignore performance, but it does show where the format is heading: more serious runtime animation infrastructure, not just cute JSON stickers.

A practical workflow

For a software team, I would treat Lottie assets like this:

  1. Design the animation in After Effects, Figma tooling, Rive/Cavalry-style tools, or a Lottie
    editor.
  2. Export as Lottie JSON or dotLottie.
  3. Put it in the repo under public/animations/.
  4. Wrap it in a small component.
  5. Trigger it from real product state.
  6. Add a reduced-motion fallback.
  7. Test on mobile.

That last part matters. Motion should respect the user. If someone has reduced motion enabled, the product should still communicate the state change without forcing animation.

@media (prefers-reduced-motion: reduce) {
  .animated-confirmation {
    display: none;
  }

  .static-confirmation {
    display: block;
  }
}

The AI angle

There is also an interesting AI angle here. Lottie is JSON, which means it is much more structured than a video file. That makes it tempting for AI tools:

  • generate a first-pass animation
  • modify colors
  • rename layers
  • simplify heavy paths
  • create variants
  • extract timing
  • map product states to animation states

I do not expect AI to replace good motion designers. But I do expect AI agents to become useful helpers around animation systems: refactoring assets, wiring them into apps, generating variants, and checking that animations are not too heavy.

The same pattern keeps showing up:

The asset is creative. The delivery system is software.

Lottie sits right at that boundary.

Takeaway

Lottie is not a replacement for Remotion, and Remotion is not a replacement for Lottie.

They solve different layers of the motion problem:

  • Lottie: small, reusable, interactive vector animations inside software.
  • Remotion: full video generation from React components and data.

If I am building a product UI, I want Lottie for the little moments that make the interface feel responsive and alive. If I am generating a reel, a demo, or a customer-specific video, I want Remotion.

Used together, they make a lot of sense: Lottie for the spark, Remotion for the story.

That is the sweet spot. Motion that is designed, versioned, testable, and actually useful.