Back to guide
Tips
Beginner

6 min read

Designing Micro-interactions: Animated Icons and Button States with Lottie

Those little morphing icons — a hamburger menu that turns into an X, a heart that fills in when you tap it — are almost never two separate animations swapped in and out. They're one Lottie file with distinct frame ranges for each state, triggered by playing the right segment.

One file, multiple segments

In After Effects, the "off" state might live at frames 0–0 (a single static frame), the transition animation at frames 0–20, and the "on" state at frame 20. Reversing setDirection or calling playSegments with the range flipped plays the same transition backward for the toggle-off action — no second animation needed.

let liked = false;

likeButton.addEventListener('click', () => {
  liked = !liked;
  if (liked) {
    animation.playSegments([0, 20], true); // play forward: empty heart -> filled
  } else {
    animation.playSegments([20, 0], true); // play backward: filled -> empty
  }
});

Keep it short

Micro-interactions read as responsive when they land in roughly 150–400ms. Anything longer starts to feel like the UI is making the user wait rather than confirming their action instantly. If a design comes in with a 1-second icon animation, that's usually a sign it was designed as a standalone piece rather than a UI transition.

Reuse one loaded instance

For icons that get triggered repeatedly (a like button, a favorite star), load the animation once when the component mounts and keep calling playSegments on that same instance. Calling loadAnimation fresh on every click re-parses the JSON and rebuilds the render tree each time — unnecessary work for something that should feel instant.

Match your existing motion language

If the rest of your interface uses a particular easing curve (ease-out for entrances, ease-in-out for toggles), ask whoever builds the animation to match it in After Effects rather than relying on the default velocity. A perfectly smooth icon animation that eases differently from every other transition on the page reads as slightly "off" even when users can't articulate why.