【Next.js】Lottie アニメーションの使い方を lottie-react の再生制御まで解説
公開日: 2026年10月8日 · 読了目安 8 分
Next.js で Lottie アニメーションを表示する手順です。lottie-react の導入、JSON の読み込み方(import と public)、動的インポートで最初の読み込みを軽くする方法、画面に入ったときだけ再生する制御、動きを減らす設定とアクセシビリティまで、コード付きで解説します。
デザイナーから届いた Lottie アニメーションを Next.js で動かす
デザイナーから、ヒーローに置くアニメーションが JSON ファイルで届いた。でも Next.js にどう載せればいいのか分からず、手が止まっている。
この JSON は、Lottie(ロッティー)という形式のアニメーションです。React では lottie-react というライブラリで表示できます。
答えは次のとおりです。JSON を public フォルダに置き、lottie-react の Lottie 部品にパスを渡せば動きます。
そのうえで読み込みを後回しにし、画面に入ったときだけ再生すると、ページを軽く保てます。
この記事で分かることは次のとおりです。
lottie-react の入れ方と、いちばん短い表示のコード
JSON を import する方法と、public から読む方法の違い
動的インポートで、最初に読み込む JavaScript を減らす方法
画面に入ったら再生し、外れたら止める制御
動きを減らす設定への対応と、読み上げソフトへの配慮
コードは Next.js 15 の App Router と、lottie-react 3 を前提にしています。
Lottie アニメーションを使う理由
Lottie は、After Effects などで作った動きを JSON に書き出したアニメーション形式です。After Effects からは、Bodymovin というプラグインで書き出すのが一般的です。
GIF や動画と比べた利点は、主に次の3つです。
図形を数値で持つので、拡大しても線がにじまない
再生・停止・特定のコマへの移動を、コードから操作できる
線や図形が中心の動きなら、同じ見た目の動画よりファイルが小さくなりやすい
反対に、写真や実写の映像には向きません。その場合は動画のほうが軽く済みます。
動画を背景にしたヒーローの作り方は、https://design-layer.com/ja/articles/nextjs-video-hero-guide で解説しています。
LottieFiles などのサイトでは、公開されている JSON を探せます。使う前に、それぞれのライセンスを確認してください。
Next.js で Lottie を表示する3つのステップ
手数の少ない順に、3段階で進めます。
Step1: lottie-react を入れて、JSON を表示する
Step2: 動的インポートで、読み込みをページの表示より後にする
Step3: 画面の出入りに合わせて、再生と一時停止を切り替える
小さなアイコンの動きなら、Step1 だけで十分です。ヒーローに置く大きなアニメーションは、Step3 まで入れてください。
Step1:lottie-react で Lottie アニメーションを表示する
まず、npm i lottie-react でライブラリを入れます。描画を担当する lottie-web も、一緒に入ります。
届いた JSON は public/lottie/plant.json に置きます。public のファイルは、/lottie/plant.json という URL で読めます。
表示する部品は、ブラウザで動かす印("use client")を付けた別のファイルに分けます。あとで再生を操作するときも、このファイルだけを直せば済みます。
"use client";
import { Lottie } from "lottie-react";
type Props = {
src: string | object;
className?: string;
};
export default function LottiePlayer({ src, className }: Props) {
return (
<Lottie
src={src}
autoplay
loop
aria-hidden="true"
className={className}
/>
);
}Lottie 部品の大きさは className で決める
Lottie の部品は、置かれた箱いっぱいに描かれます。高さのない箱では、何も見えません。
aspect-square や h-64 のように、className で大きさを決めてください。縦横比を決めておくと、表示の前後でレイアウトがずれません。
JSON を import する方法と public から読む方法
JSON は、ファイルとして import することもできます。この場合は、アニメーションのデータが JavaScript の中に入ります。
import:読み込み待ちがなく、すぐに描ける。そのかわり JavaScript が JSON の分だけ重くなる
public のパス:JavaScript は軽いまま。表示の直前に、JSON を別に取りに行く
数 KB の小さなアイコンなら import、数十 KB を超えるヒーロー用なら public が目安です。
"use client";
import LottiePlayer from "./LottiePlayer";
import plant from "@/animations/plant.json";
export function PlantIcon() {
return <LottiePlayer src={plant} className="size-12" />;
}Step2:Lottie を動的インポートして最初の表示を軽くする
lottie-react の描画エンジン(lottie-web 5.13 の全機能版)は、圧縮前で約 300KB あります。そのまま読み込むと、ページの最初の JavaScript がその分だけ増えます。
Next.js の dynamic を使うと、この部品だけを別のファイルに分けて後から読めます。ssr: false を付けると、サーバーでは描画せずにブラウザでだけ読み込みます。
古いバージョンの組み合わせでは、サーバーでの描画中に「document is not defined」というエラーが出ることがありました。ブラウザでだけ読み込めば、この心配もなくなります。
"use client";
import dynamic from "next/dynamic";
const LottiePlayer = dynamic(() => import("./LottiePlayer"), {
ssr: false,
});
type Props = {
src: string;
};
export function LazyLottie({ src }: Props) {
return (
<div className="mx-auto aspect-square w-full max-w-sm">
<LottiePlayer src={src} className="h-full w-full" />
</div>
);
}ssr: false はブラウザで動かすファイルの中に書く
Next.js 15 では、サーバーで組み立てる部品(サーバーコンポーネント)の中で ssr: false を使えません。ビルドのときにエラーになります。
そのため、上のように印を付けた LazyLottie の中で dynamic を呼びます。ページの側は、この部品を普通に置くだけです。
import { LazyLottie } from "@/components/LazyLottie";
export default function Page() {
return (
<section className="mx-auto grid max-w-5xl items-center gap-10 px-6 py-24 md:grid-cols-2">
<div>
<h1 className="text-4xl font-semibold tracking-tight">
植物のように育つ、チームのナレッジ
</h1>
<p className="mt-4 text-zinc-600">
書いたメモが自動でつながり、必要なときに見つかります。
</p>
</div>
<LazyLottie src="/lottie/plant.json" />
</section>
);
}Lottie を読み込む前に箱の大きさを確保する
動的インポートでは、部品が届くまで何も描かれません。そこで外側の div に縦横比を付け、場所を先に確保しています。
これがないと、アニメーションが現れた瞬間に、下の要素が押し下げられます。このずれは、表示の安定性を測る指標(CLS)を悪くします。
Step3:Lottie の再生を画面に入ったときだけにする
画面の外でアニメーションが回り続けると、見えない動きのために処理が使われます。スマホでは、電池の減りにもつながります。
lottie-react 3 には、画面に入ったら再生し、出たら一時停止する lottieInView という仕組みがあります。LottieInteractions で包み、autoplay は false にします。
Step1 の LottiePlayer を、次のように書き換えます。LazyLottie の Props にも label と stillFrame を足して、そのまま渡してください。
"use client";
import { useRef } from "react";
import {
Lottie,
LottieInteractions,
lottieInView,
type LottieHandle,
} from "lottie-react";
import { useReducedMotion } from "motion/react";
type Props = {
src: string | object;
className?: string;
/** 意味のあるアニメーションなら説明文。飾りなら省略する */
label?: string;
/** 動きを減らす設定のときに、止めて見せるコマ */
stillFrame?: number;
};
export default function LottiePlayer({ src, className, label, stillFrame = 0 }: Props) {
const lottieRef = useRef<LottieHandle>(null);
const reduceMotion = useReducedMotion();
return (
<LottieInteractions interactions={reduceMotion ? [] : [lottieInView({ amount: 0.3 })]}>
<Lottie
src={src}
lottieRef={lottieRef}
autoplay={false}
loop
className={className}
role={label ? "img" : undefined}
aria-label={label}
aria-hidden={label ? undefined : true}
subscriptions={{
ready: () => {
if (reduceMotion) lottieRef.current?.seek(stillFrame);
},
}}
/>
</LottieInteractions>
);
}コードのポイント
lottieInView は、画面から出ると一時停止する。戻ったときは、途中から続きを再生する
amount: 0.3 は、3割が見えたら「画面に入った」とみなす指定
動きを減らす設定の人には再生せず、stillFrame で決めたコマを止めて見せる
label を渡したときだけ読み上げの対象にし、渡さないときは aria-hidden で隠す
ブラウザのタブを切り替えている間は、ブラウザ側が描画の更新を止めます。そのため、タブの切り替えに合わせた処理は通常いりません。
lottieRef で再生と一時停止のボタンを付ける
5秒を超えて自動で動き続けるアニメーションには、止める手段を用意します。アクセシビリティの指針である WCAG の 2.2.2 が求めている対応です。
lottieRef には、play や pause などの命令が入っています。これをボタンにつなぐと、読者が自分で止められます。
ボタンは 44px 四方にして、スマホでも押しやすくしています。
"use client";
import { useRef, useState } from "react";
import { Lottie, type LottieHandle } from "lottie-react";
export function LottieWithToggle({ src }: { src: string }) {
const lottieRef = useRef<LottieHandle>(null);
const [playing, setPlaying] = useState(false);
return (
<div className="relative mx-auto aspect-square w-full max-w-sm">
<Lottie
src={src}
lottieRef={lottieRef}
autoplay
loop
aria-hidden="true"
className="h-full w-full"
subscriptions={{
play: () => setPlaying(true),
pause: () => setPlaying(false),
stop: () => setPlaying(false),
}}
/>
<button
type="button"
aria-label={playing ? "アニメーションを一時停止" : "アニメーションを再生"}
onClick={() => (playing ? lottieRef.current?.pause() : lottieRef.current?.play())}
className="absolute bottom-3 right-3 grid size-11 place-items-center rounded-full bg-white/90 text-zinc-900 shadow focus-visible:outline focus-visible:outline-2 focus-visible:outline-zinc-900"
>
<span aria-hidden="true">{playing ? "❚❚" : "▶"}</span>
</button>
</div>
);
}Lottie アニメーションの動きを減らす設定とアクセシビリティ
OS で「視差効果を減らす」などの設定にしている人は、画面の動きで気分が悪くなることがあります。ブラウザには、この設定が prefers-reduced-motion として伝わります。
lottie-react 3 は、この設定のときに autoplay の再生を始めません。最初のコマで止まった状態になります。
ただし、最初のコマが空白から始まるアニメーションもあります。その場合は Step3 の stillFrame で、完成形に近いコマを指定してください。
飾りのアニメーションは読み上げから外す
背景の植物や、見出しを飾るだけの動きは、それ自体に意味がありません。aria-hidden を付けて、読み上げソフトから隠します。
伝えたい内容は、アニメーションではなく見出しや本文のテキストに書いておきます。
意味のあるアニメーションには説明を付ける
送信の完了を示すチェックマークのように、動きで情報を伝える場合もあります。そのときは role="img" と aria-label で、内容を言葉にします。
完了のような状態の変化は、画面上のテキストでも伝えておくと確実です。
Lottie アニメーションの公開前チェックと軽くするコツ
JSON の作り方によって、ファイルは数 KB から数 MB まで差が出ます。公開の前に、サイズと動きの両方を確認してください。
Lottie の JSON ファイルを軽くする
写真を埋め込まない。画像が文字列として JSON に入ると、一気に重くなる
使っていないレイヤーや、見えない図形を書き出す前に消す
書き出す範囲を、実際に使う長さだけにする
サーバーで gzip などの圧縮がかかっているかを確かめる
After Effects の式(エクスプレッション)を使っていないなら、軽量版の LottieLight も選べます。描画エンジンは約 170KB で、全機能版の半分強です。
拡張子が .lottie のファイルは zip 形式で、lottie-react 3 ではそのまま読めません。JSON 形式で書き出してもらってください。
よくある失敗と直し方
箱に高さがなく、何も表示されない。className で大きさを決める
ページ全体のファイルに、ブラウザで動かす印を書く。Lottie を表示する部品だけに分ける
画面の外でも回し続ける。Step3 の lottieInView で止める
見出しや画像を、アニメーションが終わるまで隠す。文章は最初から見える状態にする
大きなアニメーションを、1ページにいくつも並べる。主役は1つに絞る
4つ目は、表示速度の指標である LCP を遅らせます。ヒーローの動きの付け方は、https://design-layer.com/ja/articles/nextjs-animated-hero-section-guide で解説しています。
完成した Lottie 入りのヒーローをコピーして使う方法

スクロールに合わせて、植物のアニメーションの後ろから見出しが現れる。こうした演出は、再生の制御とスクロールの計算を組み合わせる必要があります。
自分で組むと、細かな調整に時間がかかります。その場合は、完成したセクションを動かして確かめてから使う方法もあります。
DesignLayer のカタログにある「グリーン・スクロールヒーロー」は、画面に固定したままのスクロールで見出しが現れるヒーローです。中央の草木には lottie-react を使っています。
詳細ページで「Cursor 用にコピー」を押すと、組み込みの指示・ライブプレビューの URL・本体の TSX・必要な npm パッケージがまとめてコピーされます。Cursor や Claude に貼って、自分の Next.js に載せます。
閲覧とライブプレビューは無料で、アカウントもカードも要りません。無料のソースコピーは、日本時間で1日3回までです。https://design-layer.com/ja/components
載せたあとは、見出し・ロゴ・アニメーションの JSON を差し替えます。環境やテック系の LP の先頭に向いています。
Lottie アニメーションについてよくある質問
lottie-react を npm で入れれば使えます。JSON を public に置き、Lottie 部品の src にパスを渡します。
表示する部品のファイルには、ブラウザで動かす印("use client")を付けます。
まとめ:Next.js で Lottie アニメーションを使う手順
Lottie は、After Effects などの動きを JSON にしたアニメーション形式
lottie-react を入れ、JSON を public に置いて src にパスを渡す
dynamic と ssr: false で読み込みを後回しにし、箱の大きさは先に決める
lottieInView で、画面に入ったときだけ再生する
動きを減らす設定では止めたコマを見せ、飾りは aria-hidden にする
まずは Step1 のコードに、手元の JSON を1つ入れて表示してみてください。
スクロールに合わせた動き全般は https://design-layer.com/ja/articles/nextjs-scroll-reveal-guide で解説しています。ページを開いたときの演出は https://design-layer.com/ja/articles/nextjs-loading-screen-guide をご覧ください。