Lottie Animations Without the Performance Tax: A Practical Guide
How to use Lottie animations on marketing and product pages without hurting Core Web Vitals — file size, rendering, and loading strategy.
Lottie is a genuinely good format for shipping vector animation on the web — it's small compared to video, scales without blur, and can be styled at runtime. It's also easy to misuse in a way that quietly wrecks a page's performance. Here's how to keep it fast.
Keep the source file lean before it ever ships
The biggest performance cost usually isn't the Lottie player — it's the JSON file itself. A few things to check in After Effects before export:
- Remove unused layers and expressions. Anything hidden or unused still gets serialized into the JSON.
- Avoid embedded raster images inside the animation where a vector shape would do. A single embedded PNG can dwarf the rest of the file.
- Simplify masks and paths. Overly dense bezier paths (common on auto-traced illustrations) bloat file size without a visible quality gain.
A well-optimized marketing-page Lottie animation should usually land well under 100 KB. If yours is several hundred KB, it's worth a pass in LottieFiles' optimizer or a manual trim in After Effects before it goes anywhere near production.
Don't ship the Lottie player to every page
lottie-web and similar players are meaningfully sized JavaScript
dependencies. If only one section of one page uses a Lottie animation,
that's a client component boundary, not a global import — load the player
and the JSON lazily, scoped to the component that needs it, so pages without
any animation don't pay for it.
Never mark a Lottie player component priority or load it above the fold
unless it genuinely is the LCP element. Most Lottie use on marketing pages
is a supporting visual, not the hero — treat it accordingly.
Respect prefers-reduced-motion
A CSS-only prefers-reduced-motion media query does nothing to a
JavaScript-driven Lottie player — it will keep animating regardless. Read
the media query in JS and either skip initializing the player or render a
single static frame instead:
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (!reduceMotion) {
lottie.loadAnimation({ container, path: "/animations/hero.json", autoplay: true, loop: true });
}Autoplay carefully
An animation that autoplays the moment it enters the viewport, on a page
with several of them, adds up to a lot of concurrent rendering work — which
shows up as poor INP on lower-end devices. Prefer triggering playback with
an IntersectionObserver so animations only run while actually visible, and
pause them when they scroll out of view.
Between a lean source file, a lazily-loaded player, and motion that respects user preferences, Lottie can sit on a page without touching Core Web Vitals. Skip any one of those three and it usually will.
