DEV Community

Fazal Shah
Fazal Shah

Posted on

How Lottie Animations Affect Core Web Vitals (And How to Fix Issues)

Lottie animations can hurt or help your Core Web Vitals depending on how you implement them. Here's what to measure, what to fix, and what's a non-issue.


The Three Risks

Lottie can impact three CWV metrics:

  1. LCP (Largest Contentful Paint) — if a large Lottie animation is the hero element
  2. CLS (Cumulative Layout Shift) — if the container doesn't have defined dimensions
  3. INP (Interaction to Next Paint) — if too many animations are competing for CPU

TL;DR — none of these are inherent to Lottie. They're all implementation problems with known fixes.


LCP: Hero Animations

If your hero section is a Lottie animation, it may be the LCP element.

Problem: .json files are large and parse-heavy. A 150KB Lottie JSON blocks your LCP.

Fix 1: Convert to .lottie format

The same animation as .lottie is typically 30–40KB. Convert at IconKing. This is the single highest-impact change for Lottie performance.

# Before: hero.json = 145KB
# After: hero.lottie = 38KB
Enter fullscreen mode Exit fullscreen mode

Fix 2: Preload the animation file

<link rel="preload" href="/animations/hero.lottie" as="fetch" crossorigin>
Enter fullscreen mode Exit fullscreen mode

Fix 3: Don't make Lottie your LCP element

Place text content as the LCP element, with Lottie as a supporting illustration. A headline renders instantly; a Lottie file doesn't.


CLS: Undefined Container Dimensions

If you don't specify width and height, the container collapses to zero, then jumps to full size when Lottie loads. That's a CLS hit.

Problem:

// CLS: container has no dimensions
<DotLottieReact src="/hero.lottie" loop autoplay />
Enter fullscreen mode Exit fullscreen mode

Fix:

// No CLS: dimensions defined
<DotLottieReact
  src="/hero.lottie"
  loop
  autoplay
  style={{ width: 400, height: 400 }}
/>
Enter fullscreen mode Exit fullscreen mode

Or via CSS with aspect-ratio:

.lottie-container {
  width: 100%;
  aspect-ratio: 1 / 1;
  max-width: 400px;
}
Enter fullscreen mode Exit fullscreen mode

Always define dimensions. This is the most common Lottie CLS cause.


INP: Too Many Concurrent Animations

Running 8+ Lottie animations simultaneously — common on product listing pages — blocks the main thread during input handling.

Fix: Intersection Observer

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach(entry => {
      const anim = animationMap.get(entry.target);
      if (!anim) return;
      entry.isIntersecting ? anim.play() : anim.pause();
    });
  },
  { threshold: 0.1 }
);

document.querySelectorAll('[data-lottie]').forEach(el => {
  observer.observe(el);
});
Enter fullscreen mode Exit fullscreen mode

Only run animations that are visible. Pause everything else.


Measurement

Use Lighthouse before and after any Lottie optimization:

npx lighthouse https://yoursite.com --output json | grep -E "lcp|cls|inp"
Enter fullscreen mode Exit fullscreen mode

Or use PageSpeed Insights to compare mobile vs desktop CWV scores.

A well-implemented Lottie animation (correct dimensions, .lottie format, lazy-loaded) should add zero CWV penalty.


Quick Checklist

  • [ ] All animations use .lottie format (convert at IconKing)
  • [ ] All containers have explicit width and height (no CLS)
  • [ ] Hero animation is not the LCP element (or is preloaded)
  • [ ] Animations off-screen are paused via IntersectionObserver
  • [ ] Max 6–8 animations active simultaneously on mobile
  • [ ] Animations destroyed when components unmount

Summary

The .lottie format is the most impactful single change — 75% file size reduction means better LCP and lower parse time. Explicit dimensions eliminate CLS. IntersectionObserver handles INP on animation-heavy pages. All three fixes together typically improve Lighthouse scores by 5–15 points on pages with hero animations.

Top comments (0)