Lottie in Webflow: Before You Add One, Read This
When a Lottie earns its kilobytes on Webflow, when it doesn't, and the settings that keep it from wrecking your LCP.
Using lottie webflow is one of those decisions that looks simple until it isn’t. A Lottie can be the right call — lightweight, resolution-independent, interactive. It can also be a 300KB JSON blob that fires on page load, stalls your LCP, and jank-scrolls on every mid-range Android. The difference between those two outcomes is almost entirely about decisions you make before and after you upload the file. This post covers those decisions. If you’d rather have someone else make them on your project, get in touch.
What Lottie is (and isn’t)
Lottie is a JSON-based animation format created by Airbnb. An After Effects animation gets exported via the Bodymovin plugin as a .json (or the newer .lottie binary format) and played back in the browser by a small JavaScript library — Lottie-Web or the more modern dotLottie player. The output is vector-based, meaning it scales to any size without blurring, and it responds to JavaScript events: you can play, pause, reverse, or scrub it on scroll.
What Lottie is not: a replacement for video. Anything with photorealistic textures, gradients with noise, or complex particle systems will produce enormous JSON files and poor rendering performance. The format is optimized for illustration-style motion — icon animations, loaders, explainer diagrams, abstract geometric motion. If you’re working with footage-style animation, you want MP4.
Webflow supports Lottie natively. There’s a dedicated element in the Designer, no code embed required. That accessibility is part of why Lotties get overused — when something is a three-click drag-and-drop, the question “should I?” often doesn’t get asked.
The real file-size cost
The most common misconception I encounter: “Lottie is small, so performance doesn’t matter.” It’s smaller than the alternatives in the right conditions. Whether those conditions exist on your specific animation is the question.
| Animation type | Lottie | GIF | MP4 | Best choice |
|---|---|---|---|---|
| Simple icon loop (24px) | 8–15KB | 40–120KB | 60–150KB | Lottie |
| Brand illustration (full-width) | 40–80KB | 600KB–2MB | 150–400KB | Lottie or MP4 |
| Abstract geometric hero | 60–150KB | 1–4MB | 200–600KB | Lottie (optimized) or MP4 |
| Complex particle / noise motion | 200KB–1MB+ | rarely used | 300–800KB | MP4 |
| Photorealistic / video-style | not viable | not viable | 500KB–2MB | MP4 |
The table tells you that Lottie wins on simple animations and competes with MP4 on mid-complexity ones. Where it loses: anything that tries to represent photorealism or dense particle effects. Those animations produce JSON files with thousands of shape layers, and Lottie-Web has to parse and render all of them on the main thread.
The other thing the table doesn’t show is download timing. A 150KB Lottie that loads at the same time as your hero image competes for bandwidth during the most LCP-sensitive window. That’s why file size alone isn’t the full story — why your Webflow site is slow covers how these resources queue up and why the order matters.
Optimizing a Lottie before upload
An unoptimized Lottie exported directly from After Effects is almost always larger than it needs to be. The export includes debug metadata, hidden layers, unused assets, and redundant keyframe data. The optimization workflow takes five minutes and routinely cuts file size by 40–70%.
| Step | File size reduction |
|---|---|
| Remove hidden and unused layers in After Effects | 10–25% |
| Run through LottieFiles optimizer (lottiefiles.com/tools/optimize) | 15–35% |
| Trim to exact duration needed (no idle frames) | 5–15% |
| Reduce frame rate to 24fps if exported at 60fps | 10–20% |
| Convert from .json to .lottie (dotLottie) format | 40–60% |
The last step is the biggest lever and the most underused. The .lottie format is a binary container that compresses the JSON with deflate. For an animation that runs 60KB as .json, the .lottie equivalent is typically 22–30KB. Webflow’s native Lottie element accepts .lottie files — upload the binary, not the JSON, every time.
If you’re sourcing Lotties from LottieFiles’ library rather than custom-building them, download the .lottie format directly — not the JSON. Most library animations are available in both. The dotLottie version is always the right choice.
Native Webflow Lottie settings walkthrough
Webflow’s Lottie element has more settings than most people use. Knowing what each one does prevents the common configuration mistakes that turn a reasonable animation into a performance liability.
Trigger options: Autoplay on load, scroll into view, hover, scroll (progress-linked), and cursor. Each one has a different performance profile.
- Autoplay on load starts the animation as soon as the Lottie library initializes, regardless of whether the element is visible. This is the default and the most dangerous option for above-the-fold placements.
- Scroll into view fires once the element enters the viewport. Good default for below-the-fold Lotties — the animation plays when the user arrives at it.
- Hover is the lightest option performance-wise — the file still loads with the page, but the animation only runs on interaction.
- Scroll (progress-linked) ties the playhead to the user’s scroll position. This is powerful but requires a clean, smooth animation — janky keyframes become very obvious when scrubbed manually.
- Cursor maps the playhead to mouse X/Y position. Use sparingly — it runs continuously while the user’s cursor is within the element bounds.
Loop: Off by default. Turn it on only when the animation communicates something continuous (a loading state, a live indicator). A hero Lottie looping indefinitely is a distraction, not a feature.
Direction: Normal or reverse. Useful for hover-in / hover-out states where you want the animation to play forward on hover and reverse on mouse leave — set two interactions with the same Lottie at play forward and play reverse respectively.
Speed: 1x default. I rarely touch this inside Webflow — if the timing is wrong, fix it in the source file rather than faking it with a speed multiplier.
Autoplay vs scroll-trigger
This is the most consequential setting decision in the whole Lottie workflow, and most people default to autoplay without thinking through the LCP implications.
If your design calls for a Lottie in the hero, you have three options that don’t wreck your LCP:
Option 1: Scroll-triggered replay. Place the Lottie just below the fold — at the first scroll position the user reaches. Set it to “scroll into view” with play once. The hero section renders static while the LCP is measured, and the Lottie fires when the user scrolls down. Clean performance, good UX.
Option 2: CSS animation as a stand-in. For simple animations — rotating icons, pulsing dots, sliding text — CSS keyframes are zero-cost to LCP. They’re not as expressive as Lottie, but they don’t block anything. I cover this tradeoff in the CSS vs Interactions replacement section below.
Option 3: Preload with fetchpriority. Add a <link rel="preload"> tag in the <head> with fetchpriority="high" pointing to the Lottie file. This front-loads the download so the library isn’t waiting on the file when it initializes. Only use this for a single critical Lottie — preloading multiple assets defeats the purpose.
For scroll-linked animations — where the Lottie scrubs based on scroll position — the performance model changes. Scroll-progress Lotties in Webflow use Webflow Interactions 2.0 under the hood. The playhead updates on scroll events, which runs on the main thread. Keep scroll-linked Lotties simple (under 40KB) and test on a real Android device, not just Chrome DevTools throttling. DevTools mobile simulation is optimistic.
Lazy-loading Lotties
Webflow’s native Lottie element does not lazy-load by default. The .lottie or .json file is fetched as soon as the page loads, even if the element is below the fold and the user never scrolls to it. On a page with three Lotties in lower sections, that’s potentially 150–300KB of animation data competing with your hero content on initial load.
The standard fix is the Intersection Observer approach, covered in detail in Webflow lazy loading. The core pattern: store the Lottie file URL in a data-src attribute rather than the Webflow element’s source field, then use a short JavaScript snippet to swap in the real URL only when the element enters the viewport. Webflow’s Lottie element will re-initialize when the source attribute changes.
The lazy-load script lives in the site’s </body> custom code in Project Settings:
const lotties = document.querySelectorAll('[data-lottie-src]');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const src = el.dataset.lottieSrc;
el.setAttribute('data-src', src);
observer.unobserve(el);
}
});
}, { rootMargin: '200px' });
lotties.forEach(el => observer.observe(el));
The rootMargin: '200px' starts the fetch 200px before the element enters view — enough headroom that the animation is ready by the time the user scrolls to it, without loading it on initial page render.
One important caveat: this pattern only works for below-the-fold Lotties. If you’ve correctly placed your hero Lottie after the fold (as described in the section above), every Lottie on the page can be lazy-loaded. If you have a Lottie above the fold, that one should load immediately — don’t wrap it in the observer.
When to replace a Lottie with CSS or MP4
Not every animation problem needs Lottie. The right replacement depends on what the animation is actually doing.
Replace with CSS when:
- The animation is a simple state change: hover color, scale, fade, slide, rotate.
- The motion is geometric and regular — no keyframe complexity, no path animation.
- The animation is above the fold and LCP matters more than motion richness.
- The design requires instant response to user interaction — CSS transitions are frame-rate-native, Lottie has initialization overhead.
CSS has no file to download, no library to initialize, no main-thread parsing cost. For UI micro-animations — button hovers, form focus states, loading spinners, notification badges — CSS will beat Lottie on every performance metric that matters. Reach for Lottie when the animation has real storytelling value that CSS can’t replicate.
Replace with MP4 when:
- The animation file exceeds 150KB even after optimization.
- The animation has photorealistic elements, noise, or complex gradients.
- The animation has a fixed duration and doesn’t need to respond to scroll or interaction.
- You need cross-browser subtitle support or accessibility attributes.
An MP4 with a poster frame attribute and autoplay muted loop playsinline loads efficiently, shows a still frame before play, and doesn’t require a JavaScript library. For non-interactive hero animations, this is often the right call over a complex Lottie. The file will typically be larger than a well-optimized Lottie but the browser’s native video decoder handles it far more efficiently than Lottie-Web handles dense JSON on mobile.
The rule I use in practice: if the design team produced the animation in After Effects and it has more than 50 layers in the Bodymovin export, I prototype both — a Lottie at target quality and an MP4 encode at H.264 — and test both on a mid-range Android at 4G throttling. Whichever one lands under 2.5s LCP while looking good wins. Usually the Lottie wins for illustrations. Usually the MP4 wins for anything that resembles video.
The short version: Lottie earns its place on a Webflow site when the file is optimized, the trigger is scroll or interaction rather than autoplay, and the use case is illustration-style motion. It doesn’t earn its place when it’s an unoptimized export dropped above the fold because the designer liked it. Get those decisions right and Lottie adds real value — get them wrong and you’ve traded LCP points for an animation most users scroll past before it finishes loading.
Frequently asked questions
Is Lottie better than GIF or MP4 on Webflow?
For simple vector animations, yes — Lottie files are typically 10–50KB vs 500KB–2MB for GIF/MP4 at equivalent quality. For photorealistic or complex motion, MP4 with poster frame still wins.
Does Lottie hurt Webflow performance?
Only if you abuse it. A single optimized Lottie (under 50KB) is usually free. Five autoplay Lotties above the fold will push LCP past 3 seconds. Budget one Lottie hero, the rest scroll-triggered or lazy.
How do I add a Lottie file in Webflow?
Webflow has a native Lottie element. Drop it in, upload your .json or .lottie file, choose trigger (autoplay, hover, scroll, on-view). That's it — no custom code needed for 90% of uses.
What's the best Lottie optimization workflow?
Export from After Effects with the Bodymovin plugin. Run through LottieFiles' optimizer (lottiefiles.com/tools/optimize). Convert to .lottie (dotLottie) format — roughly 60% smaller than .json for the same animation.
Should I autoplay a Lottie on the hero section?
Usually no. Autoplay hero Lotties block your LCP metric because Lottie libraries init before the image paints. Either use scroll-triggered replay, or preload the Lottie with fetchpriority and hide until ready.
What size should a Lottie file be?
Under 50KB for hero placements. Under 100KB for below-the-fold. Above 150KB, consider if an MP4 with a poster frame would actually be smaller — usually yes for complex animations.
Keep reading