# 一時停止ボタンのないまま流れ続ける背景動画

Source: https://easeweb.dev/learn/background-video
Topics: 制限時間と動き > 背景の動画を一時停止できる (WCAG 2.2.2)
The fix: ホバーしなくても見える一時停止ボタンをヒーローに置き、動画そのものを止めて、止まったままにします。または、動画を5秒以内に切り詰めて1回だけ再生し、最後のコマで止まるようにします。ホバーしたときだけ現れる一時停止や、動きを減らす設定のときだけの停止では足りません。
Test with: keyboard, touch, mouse, reduced motion, screen reader
References: https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html https://www.w3.org/WAI/WCAG22/Techniques/general/G4 https://www.w3.org/WAI/WCAG22/Techniques/general/G186 https://www.w3.org/WAI/WCAG22/Techniques/general/G152 https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/video https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

あるコーヒー焙煎店のトップページは、映像から始まります。焙煎した豆が山の上に転がり落ちる映像が、「毎週月曜日に焙煎する新鮮なコーヒー」という見出しと「コーヒーを見る」ボタンの後ろ一面に流れています。デザインは映像の上に言葉だけを置いたすっきりしたもので、音に驚かせないよう、動画は消音です。再生はループで、8秒の映像が終わるとすぐ最初に戻り、ページを開いている間ずっと繰り返します。

一時停止ボタンはありません。ヒーローをクリックしても、ポインターを重ねても何も起きません。Tabキーを押すと、メニューから「コーヒーを見る」、その下の今週のコーヒーへと進みますが、動画を止めるものはどこにもありません。スマートフォンでは最初の画面いっぱいにヒーローが広がり、画面のどの文字の後ろでも、豆が転がり続けます。

## 確認できる問題

達成基準2.2.2「一時停止、停止、非表示」の対象は、動く内容のうち、自動で始まり、5秒を超えて続き、ほかの内容と並行して表示されるものです。見出しの後ろの映像は3つの条件をすべて満たします。`autoplay` で始まり、`loop` で続き、見出しやボタン、ページのほかの部分も同時に表示されています。そのため、一時停止、停止、非表示にする手段が必要ですが、このページにはありません。動画には `controls` がなく、`pause()` を呼ぶページ独自のボタンもありません。

`muted` を付けても解決しません。消えるのは音だけで（音は1.4.2「音声の制御」の対象です）、動きはそのまま残ります。しかも、音の出ない動画は、利用者がまだ何もクリックしていなくても、ブラウザーが自動再生を許します。音のある動画なら自動再生がブロックされることがあっても、消音のループはほとんどの訪問で動き出します。

## 利用者への影響

ヒーローはページの先頭にあるため、まだ何も読まないうちに動きが始まり、見出しを読んで次にどこへ進むかを決める間も、ずっと目に入り続けます。

## 自動チェックとAIの限界

この診断ツールは、`controls` のない動画のうち、音を出さずに（消音か、音声トラックがない状態で）自動で再生され、ループするか5秒を超えて続くものをすべて挙げます。そばに「一時停止」「停止」「再生」を表す名前のボタンが見つかったか、そのボタンが通常時に隠れていたり完全に透明だったり、Tabの順序から外れていたりしないかも添えます。ただし、ボタンを押して本当に動画が止まるかは確かめられず、動画から離れた場所にある操作や別の名前の操作も見つけられないため、どれも人が確認する項目です。`autoplay` 属性を使わずにスクリプトで再生する動画は、ページを読み込んだ時点で再生中の場合だけ見つかります。AIによる修正は、動きを減らす設定かどうかで再生を分ける処理を加えただけで終わることがよくありますが、その設定を見つけた人にしか効きません。ヒーローにポインターを重ねたときだけ現れる一時停止ボタンを加える修正もありますが、キーボードでは一度も表示されず、スマートフォンにはホバーするポインターがありません。

## 修正前：見出しの後ろでループする消音の動画

```html
<section class="hero">
  <video class="hero-video" src="beans.mp4" poster="beans.jpg" autoplay muted loop playsinline></video>
  <div class="hero-text">
    <h1>毎週月曜日に焙煎する新鮮なコーヒー</h1>
    <p>シングルオリジンの豆を、焙煎したその週にお届けします。</p>
    <a href="/shop">コーヒーを見る</a>
  </div>
</section>
```

```css
.hero { position: relative; display: grid; align-items: center; min-height: 70vh; overflow: hidden; }
.hero-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-text { position: relative; padding: 2rem; color: #fff; }
```

- 動画はページの読み込みと同時に始まり、`loop` によって、ページを開いている間ずっと8秒の映像を繰り返します。
- `muted` で音は消えますが、動き続けます。
- `controls` がなく、ページ独自のボタンもないため、マウスでもキーボードでもタッチでも止められません。

## 修正後：ヒーローの一時停止ボタン

```html
<section class="hero">
  <video class="hero-video" src="beans.mp4" poster="beans.jpg" muted loop playsinline aria-hidden="true"></video>
  <button type="button" class="hero-pause">
    <svg aria-hidden="true" focusable="false">
      <use href="#icon-pause"></use>
    </svg>
    <span class="visually-hidden">背景動画を一時停止</span>
  </button>
  <div class="hero-text">
    <h1>毎週月曜日に焙煎する新鮮なコーヒー</h1>
    <p>シングルオリジンの豆を、焙煎したその週にお届けします。</p>
    <a href="/shop">コーヒーを見る</a>
  </div>
</section>
```

```css
.hero { position: relative; display: grid; align-items: center; min-height: 70vh; overflow: hidden; }
.hero-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-text { position: relative; padding: 2rem; color: #fff; }
/* 暗い円の上に白いアイコン。どのコマの上でもコントラストを保つ。 */
.hero-pause {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid #fff;
  border-radius: 50%;
  background: #21160f;
  color: #fff;
}
.hero-pause:focus-visible { outline: 3px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 7px #21160f; }
```

```js
const video = document.querySelector('.hero-video');
const button = document.querySelector('.hero-pause');
// アイコンと隠した名前は、動画の実際の状態に合わせる。
function show() {
  button.querySelector('use').setAttribute('href', video.paused ? '#icon-play' : '#icon-pause');
  button.querySelector('.visually-hidden').textContent =
    video.paused ? '背景動画を再生' : '背景動画を一時停止';
}
video.addEventListener('play', show);
video.addEventListener('pause', show);
button.addEventListener('click', () => (video.paused ? video.play() : video.pause()));
// 動きを減らしたい人には、最初から止まった状態で表示する。
if (!matchMedia('(prefers-reduced-motion: reduce)').matches) video.play();
show();
```

1. ヒーローの中の言葉より前に、HTML標準の `<button>` を置きます。キーボードでは「コーヒーを見る」より先に届きます。見た目は右上の角に置くので、読む順序でも最初に来ます。ホバーしなくても、どの画面幅でも常に表示されます。
2. 白いアイコンの下に暗い円を敷き、映像の最も明るいコマでも最も暗いコマでもコントラストを保ちます。
3. ボタンで動画そのものの `pause()` と `play()` を呼びます。動画は、もう一度押すまで止まったままです。
4. アイコンと隠した名前は、動画の `play` と `pause` のイベントに合わせて「背景動画を一時停止」と「背景動画を再生」の間で切り替えます。ブラウザーが再生を始めなかったときも、ボタンは正しい状態を伝えます。
5. 動画は雰囲気づくりのためだけのものなので、`aria-hidden="true"` でスクリーンリーダーから隠し、何を操作するかはボタンに伝えさせます。
6. `autoplay` を外してスクリプトで再生を始め、動きを減らす設定にしている人には止まったままにします。これは補助です。2.2.2を満たすのはボタンで、スクリプトが動かなければ何も動きません。

これで修正前の例は直り、ループする映像もデザインもそのままで、2.2.2を満たします。

## 修正後：1回だけ再生し、5秒以内に止まる動画

```html
<section class="hero">
  <video class="hero-video" src="beans-4s.mp4" poster="beans.jpg" autoplay muted playsinline aria-hidden="true"></video>
  <div class="hero-text">
    <h1>毎週月曜日に焙煎する新鮮なコーヒー</h1>
    <p>シングルオリジンの豆を、焙煎したその週にお届けします。</p>
    <a href="/shop">コーヒーを見る</a>
  </div>
</section>
```

```css
.hero { position: relative; display: grid; align-items: center; min-height: 70vh; overflow: hidden; }
.hero-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-text { position: relative; padding: 2rem; color: #fff; }
```

1. 動画を4秒に切り詰めます。長くても5秒までです。5秒以内に終わる動きは2.2.2の対象外のため、ボタンは要りません。
2. `loop` を外します。動画は1回だけ再生されて最後のコマで止まり、そのコマが訪問中ずっと静止画として表示されます。
3. 最後のコマは、写真を選ぶときと同じように選びます。動きが終わった後に全員が見るもので、見出しの後ろに置かれるからです。
4. タイマーや、ヒーローが画面に戻ったときに再生し直すスクリプトは置きません。5秒は動きの1回分ではなく、動きのすべてです。
5. 動画は雰囲気づくりのためだけのもので、操作するものもないため、`aria-hidden="true"` でスクリーンリーダーから隠します。

これで修正前の例は直り、ボタンもスクリプトもなしに2.2.2を満たします。デザインは変わり、映像は、静止画に落ち着く短いオープニングになります。

## どの方法を選ぶか

どちらも満たします。一時停止ボタンは、デザインの中心だった終わりのない映像を残せます。ヒーローの角のボタンと数行のスクリプトが必要で、利用者がボタンを見つけるまで、豆は全員の前で動き続けます。1回だけ再生する短い動画は作る手間がほとんどなく、誰も何かを探す必要がありませんが、デザイナーはループを手放します。映像は伝えたいことを4秒で伝え、写真として成り立つコマで終わる必要があります。オープニングの映像で足りるなら短い動画を、動く映像がブランドの一部なら一時停止ボタンを選びます。

## 実装の判断

ヒーローにポインターがある間や、中にフォーカスがある間に止める仕組みは、親切として残してもかまいませんが、2.2.2が求める手段にはなりません。達成基準の解説書は、フォーカスが動く内容にある間しか続かない一時停止を認めていません。ホバーしたときだけ現れる一時停止ボタンも同じです。スマートフォンにはホバーするポインターがなく、`opacity: 0` で隠すとキーボードは見えないボタンに届き、`visibility: hidden` で隠すとキーボードはそもそも届きません。

ボタンには、ほかのアイコンボタンと同じ条件がそろっている必要があります。名前、後ろにあるどの色に対しても3:1のコントラストがあるアイコン、24×24ピクセル以上の大きさ（上のボタンは44ピクセル）、どのコマの上でも見えるフォーカス表示（上の白い枠は、内側と外側に暗い帯があります）、一緒に切り替わるアイコンと名前です。押すと名前が変わるボタンは、スクリーンリーダーによっては新しい名前を読み直さないため、利用者が使うものでも確認します。記号を知らない人のために、アイコンの横に「一時停止」と言葉を添えるサイトもあります。

利用者が選んだ状態は保ちます。`sessionStorage` などに訪問中保存し、動画を再生する前に読むことで、再読み込みしたときや同じヒーローのある次のページで、また動き出さないようにします。電池を節約するために、ヒーローが画面の外に出たら動画を止めるスクリプトはかまいませんが、利用者が止めた動画を、画面に戻ったときに再生してはいけません。

HTML標準の `controls` でも一時停止できますが、ヒーローの上に再生バーが表示され、再生位置のバーなど、ヒーローには要らない操作も付くため、多くのデザインでは上のような1つのボタンを使います。

動きを減らす設定は尊重する価値があります。一時停止ボタンの方法では、その設定のときに動画を止めたままにしています。短い動画でも、その設定のときは `autoplay` を付けないようにできます。ただし、それだけでは直りません。動きで気が散る人がその設定を知っているとは限らず、2.2.2が求めているのはページ上の仕組みです。操作をきっかけに始まるアニメーションにこの設定が求めることは、[動きを減らす設定を無視するアニメーション](/ja/learn/reduced-motion)で扱います。

短い動画の5秒は、ファイルを読み込み終えたときからではなく、動画が動き始めたときから数えます。コンテンツ管理システムで編集者がヒーローの動画を差し替えられる場合は、そこで長さを確認し、ボタンのないまま長い動画が公開されないようにします。

ほかの内容と並んで自動で動く映像には、どこでも同じ問題が起きます。どれも、同じ2つの方法で直せます。

- ページの下のほうのセクションでループする動画。たとえば、回転し続ける商品の映像。
- 動画の代わりに置かれ、終わりなくループするアニメーションGIF、WebP、Lottie。
- Vimeoの背景用オプションや、YouTubeのコントロールを非表示にして、自動再生とループを設定した埋め込み動画。

映像ではない流れる文字やカルーセルなどは、[一時停止できない、流れる文字、カルーセル、アニメーション](/ja/learn/moving-content)で扱います。脈打つボタンや回るアイコンは、ふつうは自然に止まるようにする別の方法で直します：[止まらずに動き続けるボタンやバッジのアニメーション](/ja/learn/endless-animations)。

## 修正の確認

1. ページを読み込み、動画が動き始めたときから時間を計る。5秒以内に自然に止まるなら、動いていた時間を記録して手順4へ進む。動き続けているなら次へ進む。
2. マウスを使わず、ページの先頭からTabキーを押す。一時停止ボタンはフォーカスが届く前から見えていて、映像の上でフォーカスの枠が見え、EnterキーかSpaceキーで動画が止まる。フォーカスを先に進め、ポインターを動かしても、動画は止まったままである。
3. スマートフォンで、先にヒーローに触れずに、最初の画面の一時停止ボタンをタップする。映像の最も明るいコマと最も暗いコマの上でも、ボタンが見えることを確認する。
4. ヒーローを画面の外までスクロールしてから戻り、別のページを開いて戻る。止めた動画は止まったままで、終わった短い動画は再生し直されない。
5. スクリーンリーダーで、Tabキーでボタンへ移動する。「背景動画を一時停止、ボタン」と読まれ、押した後の名前は「背景動画を再生」になる。1回だけ再生する動画では、動画について何も読まれないことを確認する。

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。ヒーロー、その動画、再生のスクリプトを変更した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。扱うのは動きだけです。映像の上の文字は、どのコマの上でもコントラストが必要で、これは[ブランドカラーや写真の上でコントラストが足りない文字](/ja/learn/text-contrast)で扱います。1秒間に3回を超えて点滅する映像は、2.3.1の別の確認項目で、閃光の分析ツールで確認します：[発作を誘発するおそれのある点滅するバナーや動画](/ja/learn/flashing-content)。音付きで再生される動画は[止められない自動再生の音声](/ja/learn/autoplay-audio)で、見るための動画は[字幕のない動画と、確認されていない自動字幕](/ja/learn/video-captions)と[キーボードで再生できない、または字幕ボタンのない動画](/ja/learn/video-player-controls)で扱います。動画が止まった後のページが落ち着いて読めるかは、人が判断する必要があります。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
