Lottie — what is it, vector animation in mobile apps

Author: IT Sectr Published: 2026-03-01 Reading time: 10 min

Lottie — an open-source library from Airbnb that renders vector animation exported from Adobe After Effects into JSON format via the Bodymovin plugin. Animations are rendered programmatically without quality loss at any screen resolution. According to GitHub (2026), Lottie is used in over 50,000 projects on iOS, Android, and Web. Learn more about other types of animation in the general guide to animation.

Key Takeaways

  • Lottie — Airbnb library for vector animation JSON from After Effects.
  • Bodymovin — plugin for exporting animation from After Effects to JSON.
  • LottieAnimationView — main View component for Android (Kotlin/Java).
  • AnimationView — main UI component for iOS (Swift, UIKit/SwiftUI).
  • .lottie format — compressed binary container, reducing size by up to 80%.

What is Lottie?

Lottie — a cross-platform library for playing vector animation, developed at Airbnb in 2015. It solves the problem of heavy video files and raster sprite sheets: a designer creates animation in After Effects, exports it via Bodymovin to JSON, and a developer embeds this file into a mobile app. Lottie renders animation programmatically via Canvas, Core Animation, or Skia, depending on the platform.

The main advantage of Lottie — vector animation scales without quality loss on any screen: from Apple Watch to 4K TVs. The animation JSON file size is typically 5–50 KB, which is tens of times smaller than the equivalent video file. According to Airbnb Engineering (2025), Lottie supports over 80% of Adobe After Effects features, including masks, effects, curves, and expressions.

Bodymovin — is a plugin for After Effects (free, GitHub) that serializes a composition into JSON format understood by the Lottie runtime. Supports After Effects CC 2018 and newer. For complex animations with many keyframes, dotLottie is recommended — a format based on Lottie JSON but compressed and packaged into a single file.

Lottie Architecture: how rendering works

Lottie uses a layered rendering architecture that adapts to platform capabilities. On Android, animation is drawn via the Canvas API — Lottie's own renderer (LottieDrawable), which does not use system animations. On iOS, Lottie relies on Core Animation Layers, providing high performance and 60 FPS. On Flutter, Lottie uses Skia Canvas via CustomPainter.

Rendering goes through three stages: JSON parsing — parsing the animation into LottieComposition (all layers, shapes, keyframes); interpolation — computing intermediate values between keyframes considering easing curves; drawing — rendering the current frame on Canvas or via Core Animation. Lottie supports hardware acceleration: on Android — acceleration via Canvas with Hardware Accelerator, on iOS — CALayer with built-in GPU acceleration of Core Animation.

PlatformRendererHardware AccelerationLibrary
AndroidCanvas (LottieDrawable)Hardware Accelerator (API 14+)com.airbnb.lottie
iOSCore Animation (CALayer)GPU (Metal, OpenGL)Lottie-iOS
FlutterSkia Canvas (CustomPainter)Impeller (Flutter 3.16+)lottie_flutter
React NativeNative bridgeDepends on platformlottie-react-native

Using Lottie on Android (Kotlin)

On Android, LottieAnimationView extends AppCompatImageView and handles the entire loading and rendering cycle. The JSON file is placed in the res/raw or assets folder. LottieAnimationView supports playback control — play, pause, resume, setFrame, setProgress, repeat, speed — and listening via AnimatorUpdateListener and AnimatorListener.

xml

<com.airbnb.lottie.LottieAnimationView
    android:id="@+id/animationView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:lottie_rawRes="@raw/loading_animation"
    app:lottie_autoPlay="true"
    app:lottie_loop="true" />
kotlin
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieListener

// Programmatic setup of LottieAnimationView
val lottieView = LottieAnimationView(context).apply {
    setAnimation(R.raw.celebrate_animation)
    repeatCount = ValueAnimator.INFINITE
    speed = 1.5f
    addAnimatorUpdateListener { animator ->
        val progress = animator.animatedValue as Float
        progressBar.progress = (progress * 100).toInt()
    }
    playAnimation()
}

// Loading from assets and caching
lottieView.setAnimation("animations/confetti.json")
lottieView.setCacheStrategy(LottieAnimationView.CacheStrategy.Strong)

// LottieDrawable — custom drawing without View
val drawable = LottieDrawable().apply {
    setComposition(
        LottieCompositionFactory.fromRawRes(context, R.raw.star)
            .addListener { composition -> composition?.let { setComposition(it); play() } }
    )
}

Android best practices: use setCacheStrategy(CacheStrategy.Strong) for frequently repeating animations — the composition is cached in memory, and each new instance does not parse JSON again. For lists (RecyclerView), use LottieAnimationView with enableMergePathsForKitKatAndAbove(true) and disableExtraScaleModeForOlderWorkarounds() to optimize rendering. For animations with a transparent background, set android:layerType="hardware" for GPU acceleration.

Using Lottie on iOS (Swift)

On iOS, AnimationView is the main Lottie class for UIKit and SwiftUI. It is added via Swift Package Manager or CocoaPods. JSON files are added to the project bundle. AnimationView automatically determines the scale (logical screen density) and uses Core Animation to render layers at 60 FPS.

swift
import Lottie

// UIKit: AnimationView with manual control
let animationView = AnimationView(name: "confetti")
animationView.frame = view.bounds
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .loop
animationView.animationSpeed = 1.5
animationView.play(fromProgress: 0, toProgress: 0.5) { finished in
    print("Animation segment finished: \(finished)")
}
view.addSubview(animationView)

// UIKit: animation with progress (for binding to events)
animationView.play(fromFrame: AnimationFrameTime(30),
                    toFrame: AnimationFrameTime(90))
swift
// SwiftUI: LottieView as UIViewRepresentable
import Lottie
import SwiftUI

struct LottieView: UIViewRepresentable {
    let name: String
    var loopMode: LottieLoopMode = .loop
    @Binding var progress: CGFloat

    func makeUIView(context: Context) -> AnimationView {
        let view = AnimationView(name: name)
        view.contentMode = .scaleAspectFit
        view.loopMode = loopMode
        return view
    }

    func updateUIView(_ uiView: AnimationView, context: Context) {
        uiView.currentProgress = progress
    }
}

// Using in SwiftUI
LottieView(name: "loading", progress: $animationProgress)
    .frame(width: 100, height: 100)

iOS best practices: for animations that start immediately after loading, use animationView.play(fromProgress: 0, toProgress: 1) with loopMode = .playOnce for one-time accent effects. For Lottie in UITableView/UICollectionView, use AnimationView with a cached animation file via LottieAnimation.cached. Rendering a large number of layers (50+) may cause FPS drops — in such cases, enable renderingEngine = .mainThread (default) or .coreAnimation for macOS.

Lottie vs video: comparison of animation formats

Lottie fundamentally differs from video files: it does not store pixels, but describes vector shapes, their transformations, and curves of change over time. Video (MP4, WebM) is a sequence of raster frames at a fixed resolution. The difference manifests in file size, scaling quality, interactivity, and performance.

ParameterLottie (JSON)Video (MP4)GIF
File size5–50 KB200–2000 KB500–5000 KB
Scaling qualityVector (infinite)Fixed (pixel)Fixed
InteractivityProgress, speed, pause, color changeNoNo
Alpha channel (transparency)NativeRequires codecSupported
Performance (CPU)Low loadMedium (decoding)High (raster decoding)

When to choose Lottie: loading icons, likes/reaction animations, onboarding screens, accent micro-animations of buttons. For complex scenes with 3D effects, realistic lighting, or photorealistic characters, video remains a more practical choice. Lottie is not designed for playing long scenes (more than 10 seconds) — the optimal duration of one animation is 2–5 seconds.

Optimizing Lottie performance

Lottie performance depends on the number of layers, complexity of masks and effects, and the renderer. To maintain 60 FPS on mid-range devices, follow these recommendations: limit the number of layers to 30–40 per scene, avoid overlapping nested pre-compositions, use dotLottie for complex animations.

kotlin
// Optimizing Lottie for RecyclerView
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable
import com.airbnb.lottie.LottieCompositionFactory

// Caching composition in memory
private val cache = LottieCompositionFactory.setCacheStrategy(CacheStrategy.Strong)

// LottieAnimationView pool for reuse
class LottiePool {
    private val pool = LinkedList<LottieAnimationView>()

    fun acquire(context: Context): LottieAnimationView {
        return pool.poll() ?: LottieAnimationView(context)
    }

    fun release(view: LottieAnimationView) {
        view.pauseAnimation()
        view.cancelAnimation()
        pool.add(view)
    }
}

// Disabling unnecessary features
lottieView.enableMergePathsForKitKatAndAbove(true)
lottieView.setHardwareAcceleration(true)
lottieView.setMaxFrame(60) // Limiting frame count

Additional optimizations: enable enableMergePathsForKitKatAndAbove(true) for devices with Android 4.4+ — this merges overlapping paths into a single path, reducing the number of draw calls. Use dotLottie instead of JSON — the binary format compresses animation by 50–80% through protobuf serialization, reducing parsing time. For animations in RecyclerView, set repeatCount = 0 (single play) and stop animation on scroll via recyclerView.addOnScrollListener. According to Airbnb Engineering Blog (2025), these measures reduce CPU load by up to 40%.

Frequently Asked Questions

How to reduce Lottie JSON size?

Use dotLottie — a binary format based on protobuf that compresses JSON by 50–80%. In After Effects, export via Bodymovin with the "Glyphs" setting = None (if text is not needed), disable unnecessary guides and guide layers. Remove invisible layers and layers with 0% opacity before export.

Lottie does not play on old devices — what to do?

Check the minimum SDK version: Lottie for Android supports API 14+, but some effects (Path Morphing, Gradient) only work on API 21+. On iOS, Lottie requires iOS 11+. For old devices, use a fallback — a static png frame from the animation. Load animations asynchronously via LottieCompositionFactory with error handling via LottieListener.onFailure.

Can I change colors in Lottie animation dynamically?

Yes, via LottieDynamicProperties or KeyPath. Set the Layer Name in After Effects (e.g., "icon-fill"), then in code: lottieView.addValueCallback(KeyPath("icon-fill"), LottieProperty.COLOR) { Color.GREEN }. This allows customizing the animation to the app theme without creating duplicate files. For iOS, use AnimationView.setValueProvider(ColorValueProvider).

Lottie vs Rive — what's the difference?

Lottie — a format for playing pre-created animation from After Effects. Rive — interactive animation with State Machine, triggers, and inputs. Lottie is suitable for passive animations (loading, likes, welcome screens). Rive is for games, interactive UI elements, animations with feedback on user actions. Rive requires its own editor, Lottie works through the familiar After Effects.

How to track Lottie animation completion?

On Android: lottieView.addAnimatorListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator?) { ... } }). On iOS: animationView.play { finished in }. In SwiftUI: use Binding for currentProgress with onChange. For Kotlin Multiplatform, use LottieAnimatable from the lottie-compose library.

Summary

  • Lottie — Airbnb library for playing vector animation JSON from After Effects.
  • Bodymovin — an export plugin After Effects → JSON, free, open-source.
  • LottieAnimationView (Android) and AnimationView (iOS) — main components for embedding.
  • dotLottie (.lottie) format reduces file size by up to 80% through protobuf compression.
  • Lottie renders via Canvas (Android), Core Animation (iOS), or Skia (Flutter) at 60 FPS.
  • Optimal Lottie animation duration is 2–5 seconds, no more than 30–40 layers per scene.
  • For interactive animations with feedback, use Rive instead of Lottie.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also