動画をファーストビューに自動再生ループで置くには、YouTubeのIFrame Player APIでプレーヤーを生成し、ミュート状態で再生を開始したうえで、再生終了イベントを拾って再生し直します。埋め込みコードにloop=1を付けるだけでは、ループも自動再生も安定しません。この記事では、受け皿のHTMLからプレーヤーの生成、画面全面をカバーするCSS、スマホでの落とし穴まで、実際に動く形のコードで順番に解説します。
結論:APIで実現できるが、まず自社MP4を検討する

先に結論を書きます。YouTube IFrame Player APIを使えば、ファーストビューでの自動再生ループは問題なく実装できます。ただし制作の現場では、まず「自社サーバーに置いた短いMP4で足りないか」を検討します。理由は3つです。
- APIを使うと
iframe_apiのスクリプトとプレーヤー一式を読み込むため、ページで最も重い場所に最も重い部品を置くことになる - YouTube側の仕様変更で挙動が変わるリスクを、ページの一等地で抱えることになる
- 10〜15秒のループ映像なら、MP4を自前で配信したほうが軽く、確実に動く
それでもAPIを選ぶ理由があるとすれば、素材がすでにYouTubeにあって差し替え運用をYouTube側で完結させたい、長尺の映像を使いたい、動画の視聴データをYouTube側で見たい、といったケースです。判断基準は記事の後半で表にまとめました。まず読み込みの重さそのものを避けたい方は、動画を軽く埋め込む方法のほうを先に読んでください。
全体像:必要な部品は3つだけ
実装は次の3点セットでできています。ここを押さえておくと、後の手順で迷いません。
| 部品 | 役割 |
|---|---|
受け皿のdiv | APIがここをiframeに差し替える。IDを付けておく |
iframe_apiのスクリプト | 読み込みが完了するとonYouTubeIframeAPIReadyが自動で呼ばれる |
YT.Playerのインスタンス | プレーヤー本体。パラメータとイベントをここで設定する |
重要なのは、onYouTubeIframeAPIReadyという関数名が固定だという点です。この名前でグローバルに定義しておくと、APIの読み込み完了時にYouTube側から呼び出されます。自分で呼ぶ必要はありません。
ステップ1:受け皿のHTMLを書く
ファーストビューの構造を作ります。動画の上にキャッチコピーを重ねる前提で、レイヤーを3層に分けておくと後の調整が楽です。
<section class="hero">
<div class="hero__video" aria-hidden="true">
<div id="hero-player"></div>
</div>
<div class="hero__overlay" aria-hidden="true"></div>
<div class="hero__inner">
<h1>ここにキャッチコピー</h1>
<p>サブコピーやボタンを置きます</p>
</div>
</section>
動画とオーバーレイにはaria-hidden="true"を付けます。背景として流しているだけの映像を、スクリーンリーダーが読み上げる対象にしないためです。id="hero-player"のdivは、後でAPIによってiframeに置き換わります。この中に何かを書いても消えるので、空のままにしておいてください。
ステップ2:IFrame Player APIを読み込む
APIのスクリプトを読み込みます。公式のリファレンスではJavaScriptで動的に挿入する書き方が紹介されていますが、単純にscriptタグで読み込んでも動きます。
<script src="https://www.youtube.com/iframe_api"></script>
<script src="/assets/hero-video.js"></script>
注意点として、この2本にはdeferやasyncを付けないでください。onYouTubeIframeAPIReadyを定義する自作スクリプトが、APIの読み込み完了より後に実行されてしまうと、コールバックが呼ばれず何も起きません。順番を確実にしたいなら、</body>の直前にこの順で並べるのが最も安全です。
ステップ3:プレーヤーを生成する

ここが本体です。hero-video.jsに次の内容を書きます。
var heroPlayer;
var HERO_VIDEO_ID = 'VIDEO_ID';
function onYouTubeIframeAPIReady() {
heroPlayer = new YT.Player('hero-player', {
videoId: HERO_VIDEO_ID,
playerVars: {
autoplay: 1,
controls: 0,
disablekb: 1,
fs: 0,
rel: 0,
playsinline: 1,
iv_load_policy: 3,
loop: 1,
playlist: HERO_VIDEO_ID,
origin: window.location.origin
},
events: {
onReady: onHeroReady,
onStateChange: onHeroStateChange
}
});
}
playerVarsで指定している内容
背景動画として使うため、操作させる要素をすべて消しています。controls: 0で操作UIを、disablekb: 1でキーボード操作を、fs: 0で全画面ボタンを、iv_load_policy: 3でアノテーションを消しています。playsinline: 1はiOSでインライン再生させるために必須です。これがないと、再生時に全画面へ切り替わってレイアウトが崩れます。
originには自サイトのオリジンを渡します。enablejsapiを有効にしてAPIから制御する場合、公式ドキュメントでも指定が推奨されている項目です。YT.Playerで生成する場合はenablejsapiが自動で有効になるため、明示的に書く必要はありません。
ステップ4:自動再生を成立させる(ミュートの正しい書き方)
ここでつまずく人が最も多いはずです。音が出る状態での自動再生は、主要ブラウザで原則ブロックされます。つまり自動再生を成立させるには、必ずミュート状態で始める必要があります。
playerVarsのmuteに頼らない
解説記事でよく見るmute: 1という指定ですが、muteはGoogleのプレーヤーパラメータ公式一覧に掲載されていません。慣用的に使われている非公式のパラメータです。動く場面は多いものの、仕様として保証されたものではないため、ファーストビューという失敗できない場所では使わないほうが安全です。
onReadyでmute()してから再生する
function onHeroReady(event) {
event.target.mute();
event.target.playVideo();
document.querySelector('.hero').classList.add('is-video-ready');
}
APIのmute()メソッドは公式に定義されたメソッドです。プレーヤーの準備が整ったonReadyの時点で確実にミュートしてからplayVideo()を呼べば、自動再生がブロックされる条件を外せます。最後の1行は、動画の準備ができたことをCSS側に伝えるためのクラス付与です。これを使って、静止画から動画へ滑らかに切り替えます。
音を出したい場合は必ずボタンを置く
document.querySelector('.hero__sound').addEventListener('click', function () {
if (heroPlayer.isMuted()) {
heroPlayer.unMute();
this.setAttribute('aria-pressed', 'true');
} else {
heroPlayer.mute();
this.setAttribute('aria-pressed', 'false');
}
});
音声付きで見せたい場合は、ユーザーの操作を起点にするしかありません。ミュート解除ボタンを重ねて置き、押されたときにunMute()を呼びます。勝手に音が鳴るサイトは離脱の原因になるため、たとえ技術的に可能でも避けてください。
ステップ5:確実にループさせる
loop: 1を指定してもループしない、という相談は非常に多いです。原因は仕様にあります。
loopにはplaylistの指定が必須
単一の動画をループさせる場合、loopだけでは効きません。playlistパラメータに同じ動画IDを指定する必要があります。ステップ3のコードでplaylist: HERO_VIDEO_IDと、videoIdと同じ値を渡しているのはこのためです。ここが抜けていると、1回再生して止まります。
それでも止まるのでイベントで補強する
function onHeroStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
heroPlayer.seekTo(0);
heroPlayer.playVideo();
}
}
loopとplaylistを正しく指定しても、再生開始位置をstartで指定していたり、通信状況が悪かったりすると、末尾で止まることがあります。再生状態の変化を拾って、終了したら先頭に戻して再生し直す処理を入れておけば確実です。制作では、この2行を保険として必ず入れています。
一部分だけを繰り返したいとき
var LOOP_START = 12;
var LOOP_END = 27;
function onHeroStateChange(event) {
if (event.data === YT.PlayerState.PLAYING) {
clearInterval(heroPlayer.__timer);
heroPlayer.__timer = setInterval(function () {
if (heroPlayer.getCurrentTime() >= LOOP_END) {
heroPlayer.seekTo(LOOP_START);
}
}, 250);
}
}
長尺の動画から「12秒目から27秒目まで」だけを繰り返したい場合は、再生位置を定期的に監視して、終点に達したら始点へ戻します。endパラメータを使う方法もありますが、終点で停止扱いになりループと相性が悪いため、この書き方のほうが安定します。
ステップ6:画面全面をカバーするCSS

YouTubeのプレーヤーは16対9の比率で表示されます。ファーストビューの縦横比はこれと一致しないため、そのままでは上下か左右に余白ができます。画面の比率に応じて拡大し、はみ出した分を隠す形にします。
.hero {
position: relative;
width: 100%;
height: 100svh;
overflow: hidden;
background: #111 center/cover no-repeat url("/img/hero-fallback.jpg");
}
.hero__video {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100vw;
height: 56.25vw; /* 100vw × 9 ÷ 16 */
min-width: 177.78svh; /* 100svh × 16 ÷ 9 */
min-height: 100svh;
pointer-events: none;
opacity: 0;
transition: opacity .8s ease;
}
.hero.is-video-ready .hero__video { opacity: 1; }
.hero__video iframe { width: 100%; height: 100%; border: 0; }
.hero__overlay {
position: absolute;
inset: 0;
background: linear-gradient(180deg, rgba(0,0,0,.45), rgba(0,0,0,.25));
}
.hero__inner {
position: relative;
z-index: 1;
display: grid;
place-items: center;
height: 100%;
color: #fff;
text-align: center;
}
ポイントは4つ
1つ目は56.25vwと177.78svhの組み合わせです。横長の画面では幅を基準に、縦長の画面では高さを基準に拡大されるので、どちらでも隙間ができません。2つ目はpointer-events: noneで、これがないとiframeがクリックを奪い、上に置いたボタンが押せなくなります。
3つ目は.heroの背景に指定したフォールバック画像です。動画が再生されるまで、そして自動再生がブロックされた環境では、この静止画が見えます。動画と同じ構図の画像を用意しておけば、再生されなくても見た目が破綻しません。4つ目は100svhで、スマートフォンのアドレスバーの伸縮によって高さが変動する問題を避けられます。
文字を読ませるためのオーバーレイ
映像の上に白文字を重ねると、明るいシーンで読めなくなります。半透明の黒をグラデーションで重ねておけば、映像の明暗が変わっても最低限のコントラストを確保できます。アクセシビリティの基準では、通常サイズの文字で4.5対1のコントラスト比が求められます。映像は常に動くので、最も明るいフレームを基準に確認してください。
ステップ7:スマホ対応とフォールバック
ファーストビューの動画で最も事故が起きるのがスマートフォンです。次の3点を必ず入れてください。
省電力モードでは再生されない前提で作る
iOSの低電力モードや、通信量節約の設定が有効な端末では、ミュートしていても自動再生がブロックされることがあります。これは制作側から回避できません。だからこそステップ6のフォールバック画像が重要になります。「再生されなくても成立する画面」を先に作り、動画は上乗せの演出だと考えてください。
スマホでは動画を読み込まない選択もある
var isSmall = window.matchMedia('(max-width: 767px)').matches;
var saveData = navigator.connection && navigator.connection.saveData;
function onYouTubeIframeAPIReady() {
if (isSmall || saveData) { return; } // 静止画のままにする
heroPlayer = new YT.Player('hero-player', { /* 以下同じ */ });
}
スマートフォンでは動画そのものを読み込まず、静止画で見せるという判断もあります。縦画面では16対9の映像を大きく拡大して切り抜くことになり、意図した構図が伝わらないケースが多いためです。通信量節約設定をsaveDataで検出して除外しておくのも、ユーザーへの配慮として有効です。
視差効果を減らす設定を尊重する
@media (prefers-reduced-motion: reduce) {
.hero__video { display: none; }
}
OSの設定で「視差効果を減らす」を有効にしているユーザーは、動きのある表現で不快感や体調不良を感じる場合があります。prefers-reduced-motionを見て動画を非表示にし、フォールバック画像だけを見せる分岐を入れておいてください。これはアクセシビリティ診断でも確認される項目です。
背景動画で使うパラメータ早見表
| パラメータ | 推奨値 | 役割 |
|---|---|---|
| autoplay | 1 | 読み込み後に再生を開始する。ミュートとの併用が前提 |
| controls | 0 | 操作UIを消す。背景として使うなら必須 |
| disablekb | 1 | キーボードでの誤操作を防ぐ |
| fs | 0 | 全画面ボタンを消す |
| playsinline | 1 | iOSでインライン再生させる。抜けると全画面になる |
| loop | 1 | ループ再生。playlistとセットでないと効かない |
| playlist | videoIdと同じ値 | 単一動画をループさせるために必要 |
| rel | 0 | 終了後の関連動画を同一チャンネル内に限定する |
| iv_load_policy | 3 | アノテーションを非表示にする |
| origin | 自サイトのオリジン | API制御時のセキュリティ対策として指定する |
表にmuteを入れていないのは意図的です。前述のとおり公式一覧にないため、onReadyでmute()を呼ぶ方法を使ってください。同じ理由で、ロゴを控えめにするmodestbrandingも入れていません。こちらは2023年8月15日に廃止されており、指定しても効果がありません。
動かないときのチェックリスト

プレーヤーが表示されない
まずonYouTubeIframeAPIReadyが呼ばれているか、関数の先頭にログを入れて確認します。呼ばれていない場合は、スクリプトの読み込み順かdeferの付け忘れが原因です。呼ばれているのに表示されない場合は、YT.Playerの第1引数に渡したIDと、HTMLのid属性が一致しているかを見てください。この関数はグローバルスコープに置く必要があるため、モジュール内やDOMContentLoaded内で定義していると呼ばれません。
再生が始まらない
ミュートの処理が抜けている可能性が高いです。onReadyの中でmute()をplayVideo()より先に呼んでいるか確認してください。順番が逆だと、再生を試みた時点でブロックされます。あわせて、その動画が埋め込みを許可しているかも確認します。チャンネル側の設定や権利者の制限で埋め込みが無効になっている動画は、どう書いても再生されません。
ループせずに止まる
playlistパラメータに動画IDを指定しているか確認してください。ここが最も多い原因です。指定済みなら、ステップ5のonStateChangeによる補強を入れます。再生位置をstartで指定している場合は、ループ時に先頭ではなくその位置へ戻したいはずなので、seekTo(0)の0を開始秒数に変えてください。
上に重ねたボタンが押せない
pointer-events: noneの指定漏れです。iframeは前面でクリックを受け取るため、これがないと下層のように見えていても操作を奪います。あわせて.hero__innerにposition: relativeとz-indexが効いているかも確認してください。
上下に黒帯が出る・構図が切れる
黒帯が出るのはmin-widthとmin-heightの計算が合っていないケースです。56.25vwと177.78svhの数値を確認してください。構図が切れるのは拡大による切り抜きなので、CSSでは解決しません。被写体を中央寄りに配置した素材を用意するか、画面幅ごとにobject-positionに相当する位置調整(transformの平行移動)を加えます。
YouTube APIと自社MP4の使い分け
| 観点 | YouTube IFrame Player API | 自社サーバーのMP4 |
|---|---|---|
| 初期読み込み | プレーヤー一式で1MB前後 | 動画ファイルのみ。2MB以下に抑えられる |
| 表示速度への影響 | 大きい。ファーストビューでは特に不利 | 小さい。posterで先に絵を出せる |
| 実装量 | JavaScriptが必要 | videoタグと属性だけで済む |
| 長尺への対応 | 得意。配信はYouTube任せ | 不向き。容量がそのまま負荷になる |
| 差し替え運用 | YouTube側で完結する | サーバーへの再アップロードが必要 |
| UIの完全制御 | ロゴやUIを完全には消せない | 完全に制御できる |
| 視聴データ | YouTube側で取得できる | 自前で計測が必要 |
判断はシンプルです。15秒前後の短いイメージ映像をループさせたいだけなら、自社MP4を選んでください。ファーストビューの表示速度は問い合わせ率に直結するため、ここに1MBのスクリプトを置く判断は慎重にすべきです。逆に、既存のブランドムービーをそのまま流用したい、映像を頻繁に差し替える運用がある、といった事情があればAPIが向いています。
もう1点、YouTubeを背景動画として使う場合はロゴやUIを完全には消せない仕様である点も踏まえてください。ブランドサイトで映像だけを見せたいという要件があるなら、この時点で自社配信を選ぶことになります。
よくある質問(FAQ)
音声付きで自動再生することはできませんか?
できません。ユーザーの操作なしに音を出す自動再生は、主要ブラウザで原則ブロックされます。制作側で回避する手段はないため、ミュートで自動再生し、ミュート解除ボタンを置く形が唯一の解になります。
ファーストビューに動画を置くとSEOで不利になりますか?
動画を置くこと自体がペナルティになるわけではありません。ただし表示速度が落ちればページ体験の評価に影響します。特にファーストビューはLCPの計測対象になりやすい場所です。フォールバック画像を軽くしておき、その画像がすぐ表示される状態を作ることが、結果的にSEO面でも有利に働きます。
限定公開の動画でも使えますか?
限定公開(リンクを知っている人のみ)の動画は埋め込めます。非公開(プライベート)の動画は埋め込めません。検索結果に出したくないだけなら限定公開を選んでください。ただしURLが分かれば誰でも視聴できる状態である点は理解しておく必要があります。
複数の動画を順番にループさせたいのですが?
playlistにカンマ区切りで動画IDを並べ、loop: 1を指定すれば、リスト全体を繰り返します。ただし動画の切り替わりでプレーヤーの読み込みが挟まり、一瞬暗転します。背景として滑らかに見せたいなら、複数の映像を1本に編集してからアップロードするほうが確実です。
WordPressでも同じ方法で実装できますか?
できます。ファーストビューはテーマのテンプレートファイル(front-page.phpなど)に直接書くことになるので、子テーマを作ってそこに実装してください。JavaScriptとCSSはwp_enqueue_scriptとwp_enqueue_styleで読み込みます。ブロックエディターの本文に貼る方法もありますが、ファーストビュー全面に広げるにはテーマ側のレイアウト制御が必要になるため、テンプレートに書くほうが確実です。
動画が読み込まれるまでの間、何が表示されますか?
.heroの背景に指定したフォールバック画像です。この記事のCSSでは、プレーヤーの準備が整った時点でis-video-readyクラスを付け、透明度のアニメーションで動画へ切り替えています。切り替えを感じさせないよう、フォールバック画像には動画の冒頭フレームを書き出したものを使うのがおすすめです。
スマホでの表示確認はどうすればいいですか?
必ず実機で確認してください。ブラウザの開発者ツールにあるスマホ表示のシミュレーションでは、自動再生の制限や低電力モードの挙動が再現されません。iOSとAndroidの両方で、通常時と低電力モード時の見え方を確認するのが最低ラインです。
まとめ
YouTube IFrame Player APIでファーストビューに自動再生ループを実装する手順をまとめます。受け皿のdivを置き、iframe_apiを読み込み、onYouTubeIframeAPIReadyでYT.Playerを生成します。自動再生はonReadyでmute()を呼んでからplayVideo()を実行して成立させ、ループはloopとplaylistの両方を指定したうえで、onStateChangeで終了を検知して再生し直す形が確実です。
CSSでは56.25vwと177.78svhで画面全面をカバーし、pointer-events: noneでクリックを通し、フォールバック画像を背景に敷きます。自動再生は環境によってブロックされる前提で、静止画だけでも成立する画面を先に作ってください。そして最後にもう一度お伝えしますが、15秒程度のループ映像なら自社サーバーのMP4のほうが軽く、確実です。ファーストビューは表示速度が最も問われる場所なので、まずそちらを検討したうえでAPIを選んでください。