Using Lottie Files Animations

  1. What is Lottie and Why Use It?
  2. Preparing and Downloading Animations
  3. Setup and Usage in React (Next.js)
  4. Animation Controls (autoplay, loop, speed)
  5. Hover and Scroll Triggers
  6. Performance: Dynamic Import & SSR
  7. Usage in React Native
  8. Color & Size Customization
  9. Accessibility (prefers-reduced-motion)
  10. Common Issues and Fixes

What is Lottie and Why Use It?

Lottie is a vector-based animation format stored as JSON. Developed by Airbnb, it allows animations created in After Effects to be played efficiently in web and mobile applications.

Compared to traditional GIF or video files, Lottie animations are much lighter, sharp at every screen size(because they're vectors), and runtime-modifiable (color, speed, stopping), which gives great design flexibility.

Advantages

  • Size: takes about a tenth of a GIF
  • Vector: stays sharp on Retina, 4K, any DPI
  • Interactive: can be triggered by hover, scroll, click
  • Cross-platform: same file works on Web, iOS, Android

When Not to Use It?

Lottie isn't suitable for very complex 3D effects or video content. In such cases video or WebGL is the better choice.

Preparing and Downloading Animations

The most practical source for ready-made animations is lottiefiles.com. It hosts thousands of free animations. If you want to create your own, you can use After Effects with the Bodymovin plugin.

Steps to Download from LottieFiles

  1. Go to lottiefiles.com and create a free account
  2. Search for the animation you need (e.g. "loading spinner")
  3. On the detail page, download the Lottie JSON option
  4. Copy the file into a suitable folder in your project (e.g. public/lotties/loading.json or src/assets/lotties/)

Creating Your Own with After Effects

  1. Install the Bodymovin plugin in After Effects
  2. Build your animation, set the timeline length
  3. Open Window → Extensions → Bodymovin
  4. Select the composition and click Render
  5. Use the resulting data.json file in your project

Note: Watch the JSON file size when downloading. Files larger than 200 KB may cause performance issues; consider simplifying layers or keyframes.

Setup and Usage in React (Next.js)

The most popular library in React projects is lottie-react. It's lightweight, modern, and TypeScript-friendly.

Package Installation

bash
npm install lottie-react

With Yarn:

bash
yarn add lottie-react

Basic Usage

Create a component and import the JSON you downloaded. In Next.js App Router this component must be marked "use client" because Lottie is a browser-only library.

tsx
"use client";

import Lottie from "lottie-react";
import animationData from "@/assets/lotties/loading.json";

export default function LoadingAnimation() {
  return (
    <Lottie
      animationData={animationData}
      loop
      autoplay
      style={{ width: 200, height: 200 }}
    />
  );
}

How It's Used in This Project

This project follows the same approach. There's a shared wrapper called CloudAnimation; you can pass any JSON via props and reuse it everywhere:

tsx
"use client";
import Lottie from "lottie-react";

export default function CloudAnimation({
  file,
  className,
}: {
  file?: object;
  className: string;
}) {
  return <Lottie animationData={file} loop className={className} />;
}

Animation Controls

lottie-react exposes many props to control playback behavior.

autoplay and loop

  • autoplay — should it start automatically when the page loads? (default: true)
  • loop — should it repeat indefinitely? (default: false)
tsx
<Lottie animationData={data} autoplay={true} loop={false} />

Speed

To control playback speed, use lottieRef and call setSpeed:

tsx
"use client";
import Lottie, { LottieRefCurrentProps } from "lottie-react";
import { useRef } from "react";
import data from "@/assets/lotties/wave.json";

export default function FastWave() {
  const lottieRef = useRef<LottieRefCurrentProps>(null);

  return (
    <Lottie
      lottieRef={lottieRef}
      animationData={data}
      onDOMLoaded={() => lottieRef.current?.setSpeed(2)}
      loop
    />
  );
}

Manual Control (play, pause, stop)

tsx
<button onClick={() => lottieRef.current?.play()}>Play</button>
<button onClick={() => lottieRef.current?.pause()}>Pause</button>
<button onClick={() => lottieRef.current?.stop()}>Stop</button>

Hover and Scroll Triggers

One of the most effective use cases is binding an animation to user interaction. Two classic patterns: play on hover and play with scroll.

Play on Hover

tsx
"use client";
import Lottie, { LottieRefCurrentProps } from "lottie-react";
import { useRef } from "react";
import data from "@/assets/lotties/heart.json";

export default function HeartButton() {
  const lottieRef = useRef<LottieRefCurrentProps>(null);

  return (
    <div
      onMouseEnter={() => lottieRef.current?.play()}
      onMouseLeave={() => lottieRef.current?.stop()}
    >
      <Lottie
        lottieRef={lottieRef}
        animationData={data}
        autoplay={false}
        loop={false}
        style={{ width: 80, height: 80 }}
      />
    </div>
  );
}

Play Based on Scroll Position

To map a scroll percentage to an animation frame use goToAndStop:

tsx
"use client";
import Lottie, { LottieRefCurrentProps } from "lottie-react";
import { useEffect, useRef } from "react";
import data from "@/assets/lotties/scroll.json";

export default function ScrollAnimation() {
  const lottieRef = useRef<LottieRefCurrentProps>(null);

  useEffect(() => {
    const totalFrames = 60;

    const onScroll = () => {
      const ratio = window.scrollY / (document.body.scrollHeight - window.innerHeight);
      const frame = Math.floor(ratio * totalFrames);
      lottieRef.current?.goToAndStop(frame, true);
    };

    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return <Lottie lottieRef={lottieRef} animationData={data} autoplay={false} loop={false} />;
}

Performance: Dynamic Import & SSR

The Lottie library uses browser APIs. When using it with SSR in the Next.js App Router, two things matter: hydration consistency and bundle size.

Disabling SSR

To render the Lottie component only on the client, use dynamic with ssr: false:

tsx
import dynamic from "next/dynamic";

const HeartButton = dynamic(() => import("./HeartButton"), {
  ssr: false,
  loading: () => <div style={{ width: 80, height: 80 }} />,
});

Lazy Loading the Animation

Not loading the animation until it's in view significantly improves performance. Use IntersectionObserver:

tsx
"use client";
import { useEffect, useRef, useState } from "react";
import Lottie from "lottie-react";

export default function LazyLottie({ data }: { data: object }) {
  const ref = useRef<HTMLDivElement>(null);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => entry.isIntersecting && setVisible(true),
      { threshold: 0.2 }
    );
    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, []);

  return (
    <div ref={ref} style={{ minHeight: 200 }}>
      {visible && <Lottie animationData={data} loop />}
    </div>
  );
}

Reducing JSON Size

  • Use lottiefiles.com/tools/json-editor to remove unnecessary layers
  • Reduce duration and number of keyframes
  • Convert frequently used animations to dotLottie format

Usage in React Native

On mobile use lottie-react-native. It offers native performance on both iOS and Android.

Installation

bash
npm install lottie-react-native lottie-ios

# For iOS
cd ios && pod install

Basic Usage

tsx
import LottieView from "lottie-react-native";

export default function Loading() {
  return (
    <LottieView
      source={require("./assets/loading.json")}
      autoPlay
      loop
      style={{ width: 200, height: 200 }}
    />
  );
}

Manual Control

tsx
import LottieView from "lottie-react-native";
import { useRef } from "react";
import { Pressable } from "react-native";

export default function Heart() {
  const lottieRef = useRef<LottieView>(null);

  return (
    <Pressable onPress={() => lottieRef.current?.play()}>
      <LottieView
        ref={lottieRef}
        source={require("./assets/heart.json")}
        autoPlay={false}
        loop={false}
        style={{ width: 80, height: 80 }}
      />
    </Pressable>
  );
}

Note: If you use Expo, expo install lottie-react-nativeinstalls the right version automatically and you don't need to run pod install.

Color & Size Customization

If the downloaded animation's color doesn't match your design, you have two options: edit it in After Effects and re-export, or modify the JSON manually.

Finding Colors in JSON

Lottie JSON stores colors as RGBA arrays in the 0..1 range. For example, deep blue looks like:

json
"k": [0.137, 0.412, 0.745, 1]

0.137 * 255 ≈ 35, 0.412 * 255 ≈ 105, 0.745 * 255 ≈ 190. So rgb(35, 105, 190). Replace these values to change the color.

Online Color Editor

The lottiefiles.com/tools/color-picker tool lets you upload a JSON file and replace all colors at once via a visual interface.

Size and Responsiveness

Because Lottie is vector based, it stays sharp at any size you set via width and height. For responsive sizing, just use CSS:

tsx
<Lottie
  animationData={data}
  loop
  className="w-full max-w-md aspect-square"
/>

Accessibility (prefers-reduced-motion)

Some users (vestibular conditions, attention sensitivity) enable the "reduce motion" setting. Respect their preference by checking the prefers-reduced-motion media query and disabling the animation:

tsx
"use client";
import Lottie from "lottie-react";
import { useEffect, useState } from "react";
import data from "@/assets/lotties/wave.json";

export default function AccessibleLottie() {
  const [reduced, setReduced] = useState(false);

  useEffect(() => {
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    setReduced(mq.matches);
    const handler = (e: MediaQueryListEvent) => setReduced(e.matches);
    mq.addEventListener("change", handler);
    return () => mq.removeEventListener("change", handler);
  }, []);

  if (reduced) return <div aria-hidden="true" />;

  return <Lottie animationData={data} loop />;
}

Common Issues and Fixes

1. Hydration Mismatch Error

Symptom:"Hydration failed" in the console.

Fix: Load the component with dynamic and ssr: false.

2. Animation Doesn't Show Up

Symptom: Nothing renders on the page.

  • Is the JSON file path correct?
  • Are you passing an object to animationData, or a URL? For a URL, use the path prop instead
  • Does the component have width and height?

3. Animation Stutters

Fix:

  • Simplify the JSON, reduce the number of layers
  • Add preserveAspectRatio: "xMidYMid meet" to rendererSettings
  • Use will-change: transform in CSS

4. JSON File Is Too Large

Fix: Switch to dotLottie format. The same animation can be up to 90% smaller:

bash
npm install @dotlottie/react-player
tsx
import { DotLottiePlayer } from "@dotlottie/react-player";

<DotLottiePlayer src="/animations/wave.lottie" autoplay loop />

With this guide you can now install Lottie animations in your project, control them, and use them with attention to performance and accessibility.

On This Page
All Rights Reserved © 2026 - sezergec.dev - Privacy Policy