Back to Blog
Engineering Opinion18 min readFebruary 19, 2026

Why SVG Animations Will Outlive Lottie (And Every Runtime That Follows)

Lottie needs a player. APNG needs a decoder. GIF needs forgiveness. CSS-animated SVG needs nothing but a browser. We break down why the zero-dependency format always wins in the long run.

I

Icora Team

Engineering

SVG icon animating with pure CSS keyframes versus a Lottie player dependency chain

In 2017, Airbnb open-sourced Lottie and the internet collectively lost its mind. Designers could finally export After Effects compositions to JSON and play them on the web, iOS, and Android with a single library. It was magic. It still is, in many cases.

But somewhere between 2017 and now, the conversation around Lottie shifted from "this is amazing" to "wait, why do I need a 50KB JavaScript player to make a checkmark bounce?" That question is the seed of this entire article.

This is not a hit piece on Lottie. Lottie is brilliant for what it was designed for: complex, cinematic, multi-layer animations that mimic After Effects timelines. But for the thing most of us actually ship, icon animation, it is a cannon where a slingshot will do. And that slingshot is CSS-animated SVG.

The Dependency Tax

Every technology has a cost of entry. For Lottie, that cost is a JavaScript runtime. lottie-web (the canonical web player) weighs between 50KB and 250KB depending on which renderer you use (SVG, Canvas, or HTML). Even the "light" build is 50KB minified and gzipped. That is the price you pay before a single frame renders.

For CSS-animated SVG, the cost of entry is zero. The animation is pure CSS inside a <style> block within the SVG file itself. The browser already knows how to execute CSS @keyframes. There is no library to load, no parser to initialize, no renderer to instantiate. The SVG is the animation.

Code
<!-- Lottie: requires a JS player -->
<script src="lottie.min.js"></script>  // 50-250KB
<script>
  lottie.loadAnimation({
    container: document.getElementById("icon"),
    renderer: "svg",
    loop: true,
    path: "/animations/checkmark.json"  // separate file
  });
</script>

<!-- CSS-animated SVG: requires nothing -->
<img src="/icons/checkmark.svg" width="24" height="24" />
<!-- The animation just plays. -->

This matters more than it looks. Every dependency you add is a dependency you maintain. lottie-web has had breaking changes across major versions. It has open issues around memory leaks on single-page apps. It requires disposal logic (destroy()) when components unmount. CSS keyframes do not have a changelog. They do not have open issues. They have been stable since 2013.

Pro Tip

A useful rule of thumb: if your animation can be described in terms of opacity, transform, color, and clip-path, it does not need a runtime. CSS handles all four natively, and those four properties cover 95% of icon animation use cases.

The File Size Reality

Proponents of Lottie often cite its small JSON files. And it is true, a Lottie JSON for a simple icon might be 3-8KB. But that number is misleading because it excludes the player. You need to amortize the player cost across your icons.

Let us do the math for a typical product page with 12 animated icons.

LottieCSS-Animated SVG
Runtime / Player~55KB (lottie-light, gzipped)0KB (native CSS)
Per-icon payload~5KB JSON (avg)~1.2KB SVG with CSS (avg)
12 icons total55 + (12 x 5) = 115KB12 x 1.2 = 14.4KB
Network requests1 (player) + 12 (JSON) = 1312 (or 1 if sprited)
Parse costJS parse + JSON parse + render initZero (native CSS path)
Total transfer~115KB~14.4KB

That is an 8x difference. And the gap widens on slower devices because Lottie's cost is not just bytes, it is CPU time. The browser has to parse JavaScript, parse JSON, build an internal scene graph, and then animate via requestAnimationFrame. CSS animations skip all of that. They run on the compositor thread, off the main thread, hardware-accelerated by default for transform and opacity.

Warning

On low-end Android devices, Lottie animations can cause visible jank if the main thread is busy. CSS animations on the compositor thread are immune to main-thread congestion. This is not a theoretical difference, it is a real-world UX gap.

Where Lottie Genuinely Wins (And Where It Does Not Matter)

Intellectual honesty matters. Lottie is genuinely superior for certain categories of animation. If you need any of the following, Lottie is the right tool:

  • **Path morphing between complex shapes**: Animating one shape into a completely different shape (e.g., hamburger menu → X icon with intermediate frames). CSS cannot interpolate between arbitrary path data.
  • **After Effects-native workflows**: If your animation team lives in After Effects and uses expressions, masks, trim paths, and parenting, Lottie preserves that entire timeline with fidelity.
  • **Multi-layer cinematic sequences**: Onboarding walkthroughs, splash screens, illustrated stories, anything with 10+ layers, nested compositions, and choreographed timing.
  • **Frame-by-frame control**: Lottie lets you scrub to any frame via goToAndStop(). CSS does not expose per-frame scrubbing without hacks.

But here is the thing: none of these describe icon animation. Icons fade in. They bounce. They spin. They draw themselves. They pulse on hover. They slide into view. These are all single-property CSS transitions. Reaching for Lottie to make an icon pulse is like importing pandas to add two numbers.

The best dependency is the one you never add. Every line of code you do not ship is a line that cannot break, cannot be exploited, and does not need to be maintained.

Portability: The Argument Nobody Talks About

A CSS-animated SVG is a single file. You can email it. You can drop it into Notion. You can paste it into a Figma frame. You can set it as a favicon. You can use it as a background-image in CSS. You can put it in an <img> tag. You can inline it in JSX. In every single one of these contexts, the animation plays.

A Lottie animation is two things: a JSON file and a player. Without the player, the JSON is meaningless. This creates a hard coupling that limits where the animation can live.

ContextCSS-Animated SVGLottie
<img> tagAnimates automaticallyDoes not work (needs JS player)
CSS background-imageAnimates automaticallyDoes not work
Email (HTML)Works in modern clientsDoes not work
Figma / SketchRenders (static, but visible)Requires plugin
React / Vue / SvelteInline SVG, full DOM controlRequires wrapper component + player
Native iOS / AndroidWebView or native SVG renderRequires lottie-ios / lottie-android
Markdown / Docs![icon](icon.svg) worksRequires custom embed
No-code tools (Webflow)Drag and dropRequires custom code embed

This portability is not a nice-to-have. It is the reason SVG won the icon format war in the first place. SVG replaced icon fonts because it was more portable, one file, works everywhere, scales to any size, supports color. CSS-animated SVG extends that same advantage into motion.

The Maintenance Graveyard

Let us talk about what happens two years from now. Your codebase has 80 Lottie animations. The lottie-web package has moved to v6. There are breaking API changes. The SVG renderer has been deprecated in favor of a Canvas-only mode. Your React wrapper (lottie-react, react-lottie, react-lottie-player, yes, there are three competing wrappers) has not been updated in 14 months.

This is not speculation. This is the current state of the Lottie ecosystem. The original lottie-web by Airbnb has 800+ open issues. The community is fragmented across forks. The Bodymovin plugin (the After Effects exporter) has compatibility issues with newer AE versions. The DotLottie format was introduced to fix shortcomings of the original JSON format, splitting the ecosystem further.

Now consider the alternative. Your codebase has 80 CSS-animated SVGs. Two years from now, CSS @keyframes still works. It has worked since Chrome 43. It will work in Chrome 243. The W3C CSS Animations specification is a Recommendation, the highest stability level. There is no wrapper library to abandon you. There is no exporter plugin to break. The format is the standard.

Pro Tip

When evaluating animation technologies, ask: "What does this look like in 5 years if the maintainer disappears?" For Lottie, the answer is "a broken build." For CSS-animated SVG, the answer is "it still works."

The "But Designers Need After Effects" Myth

The strongest argument for Lottie has always been the designer workflow: animate in After Effects, export with Bodymovin, done. But this argument has a hidden assumption, that the animation is complex enough to require After Effects in the first place.

For icon animation, it almost never is. Here is what the typical icon animation actually looks like:

Code
/* A "fade in" icon entrance */
@keyframes fade-in {
  from { opacity: 0; transform: scale(0.8); }
  to   { opacity: 1; transform: scale(1); }
}

/* A "draw" effect (stroke dasharray) */
@keyframes draw {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

/* A "pulse" loader */
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.15); }
}

These are 3-5 line keyframe blocks. No designer needs After Effects to define "fade in from 80% scale." The overhead of opening AE, creating a composition, animating two properties, exporting via Bodymovin, and then integrating the 5KB JSON with a 50KB player, to achieve what 4 lines of CSS already do, is an engineering anti-pattern dressed up as a design workflow.

The better workflow is: design the static icon in your favorite tool, export the SVG, and let the animation platform handle the motion. The designer decides what the icon looks like. The system decides how it moves. This separation of concerns is exactly what Icora provides.

Interactivity Without JavaScript

One of the most underrated advantages of CSS-animated SVG is native interactivity. Because the animation is CSS, it responds to CSS selectors. Hover, focus, and media queries work out of the box.

Code
/* Animation plays only on hover, zero JS */
svg[data-icora-animate="hover"] .icora-anim-group-abc {
  animation-play-state: paused;
}
svg[data-icora-animate="hover"]:hover .icora-anim-group-abc {
  animation-play-state: running;
}

/* Respects reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  [class*="icora-"] {
    animation-duration: 0.01ms !important;
  }
}

With Lottie, achieving hover-triggered playback requires JavaScript event listeners (mouseenter, mouseleave), manual play/pause calls, and often a wrapper component that manages state. It is doable, but it is code you have to write, test, and maintain.

The accessibility story is even more stark. The prefers-reduced-motion media query is a one-liner in CSS. In Lottie, you need to listen to window.matchMedia("(prefers-reduced-motion: reduce)") in JavaScript and conditionally stop the player. Most Lottie implementations in the wild do not do this, which means they are shipping motion to users who explicitly asked for less of it.

The Decision Framework

After building animation systems for both formats, here is the framework we use internally at Icora to decide between CSS-animated SVG and Lottie.

Use CSS-Animated SVG

Icons, logos, UI feedback, loading indicators, hover effects, entrance animations, attention seekers, continuous loops, anything with < 5 animated properties.

Use Lottie

Onboarding sequences, illustrated stories, complex morphs, After Effects compositions with expressions, frame-scrubbing interactions, animations with 10+ layers.

The dividing line is complexity. If the animation can be described as a combination of opacity, transform, stroke-dashoffset, clip-path, and color, CSS wins on every axis: size, performance, portability, maintainability, accessibility. If the animation requires path morphing, nested timelines, or frame-level control, Lottie is the right tool.

For icons specifically, we have never encountered a case where Lottie was the better choice. Not once. Icons are small, geometrically simple, and animate on a handful of properties. They are the perfect candidate for CSS animation.

How Icora Builds on This Philosophy

This is not just an opinion piece. We built the Icora animation system around the zero-dependency principle. When you animate an icon in the Icora Studio, here is exactly what happens:

  • **26 curated presets**: Entrance (draw, fade, pop, bounce, rubber band, flip, slide, zoom, typewriter, morph), Attention (shake, swing, jello, tada, heartbeat, wiggle, wobble, head shake), Continuous (pulse, float, spin, blink, breathe, color cycle), and Exit (fade out, slide out).
  • **Per-icon customization**: Duration, delay, stagger, easing, iterations, direction, all adjustable in the panel, all baked into the SVG on export.
  • **Self-contained output**: The exported SVG has everything inside it. No external stylesheet, no JavaScript file, no player library. One file, one <style> block, done.
  • **Collision-proof**: Every animation injection uses a random unique suffix. You can put 50 animated SVGs on the same page and they will never interfere with each other.
  • **Accessibility by default**: Every animated SVG includes a @media (prefers-reduced-motion: reduce) query. You do not have to remember to add it. It is always there.
  • **External control via data attribute**: The data-icora-animate attribute lets developers pause, resume, or switch to hover-only mode from external code, without reaching into the SVG internals.
  • **Strip with one click**: Buyers on the marketplace can download any animated pack with animations stripped. The result is a clean, static SVG with zero residue from the animation system.

The marketplace angle is worth highlighting. When a creator publishes an animated icon pack, the animations travel with the icons. Buyers see them animate in the preview. They can download with the creator's animations preserved, or strip them and apply their own, or download static. The animation is an enhancement, not a lock-in.

The Long View: Standards Always Win

History is littered with proprietary formats that solved real problems but were eventually absorbed by open standards. Flash gave us rich interactive web content, then HTML5 Canvas, CSS Animations, and the Web Animations API ate its lunch. Silverlight gave us video streaming, then HLS and DASH made it obsolete. jQuery gave us cross-browser DOM manipulation, then browsers standardized querySelector and fetch.

Lottie is in the same arc. It solved a real problem in 2017: browsers could not easily animate complex vector compositions. But since then, CSS has gained clip-path animations, individual transform properties, the :has() selector, container queries, scroll-driven animations, and the View Transitions API. The platform keeps closing the gap.

We are not predicting Lottie's death. It will continue to serve its niche, complex, cinematic, multi-layer animation, for years to come. But for the 90% of web animation that is icon motion, UI feedback, loading states, and hover effects, the standard won. CSS-animated SVG is the format that needs nothing, works everywhere, and will outlast every runtime that tries to replace it.

The web is a platform that rewards simplicity. The simplest animation format is the one that is already built into the browser. That format is CSS.

Icora ships 26 animation presets that bake directly into your SVGs, zero runtime, zero dependencies, zero maintenance. Generate an icon, pick an animation, export, and ship. Try it free at icora.design/create.

Try Icora Free
Tags:SVG vs LottieSVG animationCSS animation iconsLottie alternativeanimated SVG icons

Found this helpful? Share it!

Ready to Create Stunning Icons?

Put these principles into practice with Icora's AI-powered icon generator, professional studio tools, and developer-ready export.

Start Creating Free