【Next.js】背景動画のヒーローの作り方を解説|自動再生・軽量化・スマホ対応
公開日: 2026年9月12日 · 読了目安 13 分
Next.js のファーストビューに背景動画(ヒーロー動画)を置く方法をコード付きで解説。自動再生に必要な属性(muted・playsInline など)、ffmpeg での軽量化、再生前の静止画と表示速度、スマホや省データ設定で静止画に切り替える分岐、文字が読めるオーバーレイまで。
背景動画ヒーローが自動再生されない・重いときの答え
Next.js で LP を作っていて、ファーストビューの背景に動画を流したい。けれど動画を置いてみると、次のようなつまずきがよく起きます。
自動再生されない
読み込み中に黒い画面が出る
ページが重くなった
答えはシンプルです。動画のタグに、muted と playsInline を含む5つの指定をそろえて付けます。
動画のファイルは、10 秒前後・音声なしに圧縮します。
スマホや省データ設定の人には、再生前に表示する静止画だけを見せます。見出しの下には暗いオーバーレイを敷きます。
この記事で分かることは次のとおりです。
背景動画のヒーローが向いているサイトと、向いていないサイト
そのまま使える Next.js のヒーロー動画コンポーネント
自動再生される条件と、されないときの対処
動画ファイルの軽量化と、再生前に見せる静止画の作り方
スマホ・省データ・動きを減らす設定のときに静止画へ切り替える方法
背景動画のヒーローが向いているサイト・向かないサイト
背景動画が力を発揮するのは、映像そのものが商品の魅力になる場合です。たとえば次のようなものは、静止画より動画の方が多くを伝えます。
飲食店や宿泊施設の雰囲気
イベントの熱気
映像制作の実績
ハードウェア製品の質感
一方、SaaS や業務ツールの LP では、動画が見出しと CTA から視線を奪いがちです。
この場合は、短い入場アニメーションを付けた静止画ヒーローの方が成果につながりやすくなります。作り方は https://design-layer.com/ja/articles/nextjs-animated-hero-section-guide で説明しています。
迷ったときは、まず静止画ヒーローで公開し、映像素材がそろってから動画に差し替えても遅くありません。
後から差し替えやすいよう、ヒーローの背景部分を1つのコンポーネントに分けておくと楽です。
Next.js の背景動画ヒーロー:基本のコンポーネント
まずは一番シンプルな形です。動画のタグ(video 要素)は、ブラウザの機能だけで再生されます。
そのため、この部品はサーバーで組み立てる部品(Server Component)のままで動きます。
動画ファイルと、再生前に表示する静止画(poster)は public/videos/ に置く想定です。
export function VideoHero() {
return (
<section className="relative isolate flex min-h-[100svh] items-end overflow-hidden px-6 pb-20 text-white md:px-12">
<video
className="absolute inset-0 -z-10 h-full w-full object-cover"
autoPlay
muted
loop
playsInline
poster="/videos/hero-poster.jpg"
aria-hidden="true"
>
<source src="/videos/hero.webm" type="video/webm" />
<source src="/videos/hero.mp4" type="video/mp4" />
</video>
{/* 文字を読みやすくするための暗いグラデーション */}
<div
aria-hidden="true"
className="absolute inset-0 -z-10 bg-gradient-to-t from-black/75 via-black/35 to-black/10"
/>
<div className="max-w-2xl">
<h1 className="text-4xl font-semibold leading-tight md:text-6xl">
海辺の一棟貸し、週末の予約受付中
</h1>
<p className="mt-5 text-base text-white/80 md:text-lg">
朝は波の音で目覚め、夜はテラスで焚き火を囲む。
</p>
<a
href="#reserve"
className="mt-8 inline-flex rounded-full bg-white px-6 py-3 font-medium text-zinc-950 transition hover:bg-white/90"
>
空室を確認する
</a>
</div>
</section>
);
}背景動画は5つの属性をセットで付ける(自動再生の条件は muted と playsInline)
autoPlay だけでは足りません。主要なブラウザは、音が出る動画の自動再生をブロックします。
muted で無音にすると、自動再生が許可されます。
iPhone の Safari では、動画が全画面プレーヤーに切り替わることがあります。これを防ぐのが playsInline です。
残りの2つは、繰り返し再生する loop と、再生が始まるまで表示する静止画の poster です。
自動再生の条件になるのは muted と playsInline です。この5つはセットで覚えてください。
WebM と MP4 を両方用意する
source は上から順に試されます。圧縮率の高い WebM を先に、対応範囲の広い MP4 を後に並べます。
WebM を用意する時間がなければ、MP4(H.264)1本でもほとんどのブラウザで再生できます。
装飾の背景動画には aria-hidden を付ける
背景動画が雰囲気づくりだけなら、aria-hidden="true" でスクリーンリーダーから隠します。伝えたい情報は、動画の中ではなく見出しと本文に文字で書きます。
背景動画が自動再生されないときの確認ポイント
コードが正しくても、端末の設定で自動再生が止まることがあります。代表的なのは、iPhone の低電力モードです。
この状態では動画が再生されず、再生前の静止画だけが表示されます。だからこそ、静止画だけでも成り立つヒーローにしておく必要があります。
自分の環境で再生されないときは、次の順で確認します。
無音の指定(muted)と、全画面にしない指定(playsInline)が付いているか
動画に音声トラックが残っていないか(muted がない場合に効く。ファイルも軽くなる)
動画ファイルのパスが正しいか
動画の圧縮形式(コーデック)が H.264 か
iPhone の低電力モードがオンになっていないか
音声トラックは、ffmpeg の -an で消せます。
パスは、public/ 以下のファイルなら / から書きます。
H.265 で書き出した MP4 は、ブラウザによって再生できないことがあります。
それでも再生が始まらない場合は、ブラウザで動く部品(Client Component)から再生を始める方法があります。
具体的には、動画の要素を直接さわって無音に設定し直し、play() を呼びます。
次の章のコードで、その形を紹介します。
背景動画を ffmpeg で軽量化する方法
背景動画で一番多い失敗は、ファイルが大きすぎることです。撮影したままの動画は数十 MB になることも珍しくありません。
ヒーロー用の動画は、次の目安まで削ります。
長さは 6〜15 秒。ループのつなぎ目が目立たない場面を選ぶ
横幅は 1280px 程度。全画面でも、暗いオーバーレイの下なら粗さは目立ちにくい
音声トラックは削除する
ファイルサイズは数 MB 以内を目安にする
変換には、動画変換ツールの ffmpeg が使えます。
次のコマンドで、MP4・WebM・再生前に表示する静止画の3つを作れます。
# MP4(H.264): 10 秒・横 1280px・音声なし・先頭から再生しやすい配置
ffmpeg -i source.mov -t 10 -an -vf "scale=1280:-2,fps=30" -c:v libx264 -crf 28 -preset slow -pix_fmt yuv420p -movflags +faststart public/videos/hero.mp4
# WebM(VP9): 同じ条件でより小さく
ffmpeg -i source.mov -t 10 -an -vf "scale=1280:-2,fps=30" -c:v libvpx-vp9 -crf 38 -b:v 0 public/videos/hero.webm
# poster 画像: MP4 の最初のフレームを書き出す
ffmpeg -i public/videos/hero.mp4 -frames:v 1 -q:v 3 public/videos/hero-poster.jpgcrf の数値で背景動画の画質とサイズを調整する
crf は数値が大きいほど圧縮が強くなり、ファイルが小さくなります。
まず上の値で書き出し、粗さが気になれば数値を2〜3ずつ下げます。オーバーレイを敷く前提なら、思ったより強めに圧縮しても目立ちません。
再生前の静止画は表示速度にも関わる
再生前に表示する静止画は、LCP(ページの主要な内容が表示されるまでの時間)の対象になります。
この静止画が重いと、動画を軽くしても表示速度の評価は上がりません。
静止画も圧縮し、動画の1コマ目と同じ絵にしておきます。そうすれば、再生が始まる瞬間に画面が切り替わって見えません。
動画ファイルが大きくなる場合は、public/ に置かず、CDN やストレージサービスから配信することも検討してください。
スマホと省データ設定では背景動画を静止画にする
スマホのモバイル通信で背景動画を毎回読み込ませると、通信量とバッテリーを消費します。
次の人には、再生前の静止画だけを見せるのが現実的です。
画面の小さい端末の人
動きを減らす設定(prefers-reduced-motion)の人
省データ設定の人
CSS の hidden で動画を隠すだけでは、動画のダウンロードが止まらないことがあります。
そこで、条件を満たしたときだけ動画ファイル(source)を追加する、ブラウザで動く部品にします。
そうすれば、不要な読み込みが発生しません。一時停止ボタンも付けておきます。
"use client";
import { useEffect, useRef, useState } from "react";
type HeroVideoProps = {
mp4: string;
webm?: string;
poster: string;
};
type NavigatorWithConnection = Navigator & {
connection?: { saveData?: boolean };
};
export function HeroVideo({ mp4, webm, poster }: HeroVideoProps) {
const ref = useRef<HTMLVideoElement>(null);
const [enabled, setEnabled] = useState(false);
const [playing, setPlaying] = useState(false);
// 画面幅・動きを減らす設定・省データ設定を見て、動画を使うか決める
useEffect(() => {
const isWide = window.matchMedia("(min-width: 768px)").matches;
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const saveData = (navigator as NavigatorWithConnection).connection?.saveData === true;
setEnabled(isWide && !reduceMotion && !saveData);
}, []);
// source を追加したあとに読み込みと再生を始める
useEffect(() => {
const video = ref.current;
if (!enabled || !video) return;
video.muted = true;
video.load();
video
.play()
.then(() => setPlaying(true))
.catch(() => setPlaying(false)); // ブロックされたら poster のまま
}, [enabled]);
function togglePlayback() {
const video = ref.current;
if (!video) return;
if (video.paused) {
video.play().then(() => setPlaying(true)).catch(() => {});
} else {
video.pause();
setPlaying(false);
}
}
return (
<>
<video
ref={ref}
className="absolute inset-0 -z-10 h-full w-full object-cover"
poster={poster}
muted
loop
playsInline
aria-hidden="true"
>
{enabled && webm ? <source src={webm} type="video/webm" /> : null}
{enabled ? <source src={mp4} type="video/mp4" /> : null}
</video>
{enabled ? (
<button
type="button"
onClick={togglePlayback}
className="absolute bottom-6 right-6 rounded-full bg-black/50 px-4 py-2 text-sm text-white backdrop-blur"
>
{playing ? "動画を停止" : "動画を再生"}
</button>
) : null}
</>
);
}動画ヒーローの本体はサーバー側の部品のまま使う
HeroVideo は、背景部分だけのブラウザで動く部品です。
見出しやボタンを含むヒーロー本体は、サーバーで組み立てる部品のままにします。
基本形の動画タグの代わりに、HeroVideo を置きます。
見出しの HTML はサーバーで出力されるので、検索エンジンにもそのまま伝わります。
<section className="relative isolate flex min-h-[100svh] items-end overflow-hidden px-6 pb-20 text-white">
<HeroVideo mp4="/videos/hero.mp4" webm="/videos/hero.webm" poster="/videos/hero-poster.jpg" />
<div aria-hidden="true" className="absolute inset-0 -z-10 bg-gradient-to-t from-black/75 via-black/35 to-black/10" />
{/* 見出し・本文・CTA */}
</section>背景動画に一時停止ボタンを付ける理由
Web アクセシビリティの基準である WCAG 2.2 では、自動で始まり 5 秒より長く続く動きには、止める手段が求められています(達成基準 2.2.2)。
ループする背景動画はこれに当たるため、小さな停止ボタンを置いておきます。
背景動画の上でも見出しが読めるオーバーレイ
動画は明るい場面と暗い場面が入れ替わるため、ある瞬間だけ見出しが読めなくなることがあります。
動画の上に半透明の黒を敷き、どのコマでも白い文字が読める状態にします。
見出しを下寄せにするなら、下から上に薄くなるグラデーション(bg-gradient-to-t from-black/75)が自然です。中央に置くなら、全体に bg-black/40 程度を敷きます。
明るい動画で白文字がまだ弱いときは、文字に影を付けるよりオーバーレイを濃くする方が読みやすくなります。
最後に、動画の一番明るいコマで止めて見出しを確認してください。ここで読めれば、どの瞬間でも読めます。
動画ヒーローでよくある失敗と直し方
poster がなく、読み込み中に黒い四角が表示される
muted を付け忘れたうえに音声トラックが残っていて、自動再生がブロックされる
撮影したままの数十 MB の動画を置いている
ヒーローの高さが決まっておらず、動画の読み込み後にレイアウトがずれる(min-h で高さを先に確保する)
ループのつなぎ目で画面が跳ねる
点滅や激しいフラッシュを含む映像を使っている
YouTube の埋め込みを背景に使う方法もあります。ただ、背景全面には向きません。
プレーヤーの読み込みが重く、操作ボタンや余白も出やすいためです。
短いループ動画を自分で用意する方が、見た目も表示速度も整えやすくなります。
完成した動画ヒーローをコピーして使う方法

ここまでの内容で、背景動画のヒーローは作れます。
ただ、次の点まで整えるには、試行錯誤の時間がかかります。
映像の切り替わりと見出しの入場タイミング
文字の大きさと余白のバランス
DesignLayer は、人が組んだ React + Tailwind CSS のモーション付きセクションを、ブラウザでライブプレビューしてからコピーできるカタログです。
ヒーローの動きを実際に見て選び、映像の URL と見出しだけを差し替えて使えます。
閲覧は無料で、カード登録も要りません。https://design-layer.com/ja/components
Copy for Cursor を押すと、統合の指示・ライブプレビューの URL・本体の TSX・npm 依存がまとめてコピーされます。Cursor や Claude にそのまま渡せます。
無料アカウントでは、無料サンプル10個を無料アカウントで回数制限なくコピーでき、動画プロンプトは月1回です。Free では MCP に接続できません。カタログ全体は30日ビルドパス($19の1回払い、自動更新なし)、Lifetime Access(先着100名の$79の1回払い)、Plus(月額 $9、いつでも解約可)です。公開前に、音が出る設定になっていないかだけは必ず確認してください。
見出しの入場アニメーションを Motion(旧 Framer Motion)で付けたい場合は、https://design-layer.com/ja/articles/nextjs-framer-motion-guide を参考にしてください。
背景動画のヒーローについてよくある質問
背景全面には向きません。プレーヤーの読み込みが重く、操作ボタンや黒い余白が出やすいためです。
背景用には、自分で書き出した短い MP4 や WebM を使います。説明用の長い動画を見せたい場合は、ヒーローの下に別のセクションとして埋め込みます。
まとめ:Next.js で背景動画ヒーローを作る手順
背景動画は、映像が商品の魅力になるサイトで使う。SaaS などは静止画ヒーローも検討する
動画のタグに5つの指定(無音・自動再生・繰り返し・全画面にしない・再生前の静止画)をそろえる。自動再生に欠かせないのは無音と全画面にしない指定
動画は 10 秒前後・横 1280px 程度・音声なしに圧縮し、静止画も軽くする
スマホ・省データ・動きを減らす設定では動画を読み込まず、静止画にする
オーバーレイで見出しを読めるようにし、一時停止ボタンを置く
まずは手元の素材を ffmpeg で圧縮し、基本形の VideoHero に入れて表示を確かめてみてください。
ヒーロー全体の動きまで整った形から始めたい場合は、DesignLayer のカタログでライブプレビューしてから選べます。https://design-layer.com/ja/components


