gazou-compressor.jp

動画/アニメのループ・自動再生とアクセシビリティ実務

要点(TL;DR)

1. 埋め込みテンプレ(安全なデフォルト)

<video
  src="/anim/ui.mp4"
  autoplay muted loop playsinline
  width="420" height="240"
  aria-label="操作の流れ(再生は自動で停止可能)"
></video>

poster は初期表示のLCPを悪化しないよう適切に圧縮した静止画を指定します。

1.5 ブラウザの自動再生ポリシー(要点)

データセーバー配慮
判定は一律ではありません。判定不能時もあるため、自動再生を前提にしないUI(静止画+再生ボタン)を優先。

1.8 プラットフォーム別ポリシー速見表

代表的な環境の傾向。個々のバージョン差は公式ドキュメントを確認。

| 環境 | 自動再生(音声) | muted+inline | 省データ/低電力 | 備考 |
|------|-----------------|--------------|------------------|------|
| iOS Safari | × | ○(必須) | ×/× によって停止 | フルスクリーン化を避ける |
| Android Chrome | △ | ○ | △ | Data Saver で停止あり |
| Desktop Chrome | △ | ○ | – | ユーザー操作履歴に依存 |
| Desktop Safari | △ | ○ | – | 自動再生許可設定あり |

2. reduced-motion(動きが苦手な利用者への配慮)

@media (prefers-reduced-motion: reduce){
  video[autoplay]{
    animation: none !important;
  }
}

JS で matchMedia('(prefers-reduced-motion: reduce)') を検出し、再生停止/静止画に切り替えるのも有効です。

// Reactの例: reduced-motion なら自動停止 + ポスターに置換
import { useEffect, useRef } from 'react';
export function SafeAutoPlayVideo(){
  const ref = useRef<HTMLVideoElement>(null);
  useEffect(() => {
    const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
    const v = ref.current; if(!v) return;
    if (mq.matches) { v.pause(); v.removeAttribute('autoplay'); }
  }, []);
  return <video ref={ref} autoPlay muted loop playsInline width={420} height={240} poster="/poster/ui.jpg" />
}

2.5 ユーザー主導の制御(アクセシビリティ)

キーボード操作やスクリーンリーダーでの可用性を担保します。

<button aria-pressed="false" aria-controls="demo" id="toggle">再生</button>
<video id="demo" muted playsinline width="420" height="240" aria-label="UIの操作例"></video>
<script>
  const btn = document.getElementById('toggle');
  const v = document.getElementById('demo');
  btn.addEventListener('click', async () => {
    const playing = btn.getAttribute('aria-pressed') === 'true';
    if (playing) { v.pause(); btn.setAttribute('aria-pressed','false'); btn.textContent='再生'; }
    else { await v.play().catch(()=>{}); btn.setAttribute('aria-pressed','true'); btn.textContent='停止'; }
  });
</script>

3. 代替テキスト/字幕

<video ... aria-label="ボタンの状態遷移">
  <track kind="captions" src="/captions/ui.vtt" srclang="ja" label="日本語" default />
</video>

意味伝達が重要なら字幕/説明文を併用し、動きに依存しない理解手段を提供します。

3.5 パフォーマンス設計(LCP/INPを壊さない)

3.8 視認外は自動停止(IntersectionObserver)

const io = new IntersectionObserver((entries)=>{
  for (const e of entries){
    const v = e.target as HTMLVideoElement;
    if (e.isIntersecting) v.play().catch(()=>{}); else v.pause();
  }
}, { threshold: 0.25 });
document.querySelectorAll('video[autoplay][muted]').forEach((v)=> io.observe(v));

スクロールで見えないときは停止し、CPU/バッテリーを節約します。

4. 公開前チェック

5. 実機検証プロトコル(10分)

  1. iOS/Android/デスクトップの3系で 初回訪問 をテスト(シークレットウィンドウ)。
  2. 省データ/低電力モードをONにし、代替UIが出るか確認。
  3. キーボード操作で再生/停止/フォーカス遷移が可能か。
  4. LCP/CLS/INP を簡易計測(DevTools/Performance, Web Vitals 拡張)。

6. 実装パターン集

FAQ

FAQ(拡張)

1自動再生に preload は必要?
初期は none/metadata を推奨。視認直前に遅延ロード。
2アニメGIFの代わりに動画?
ほぼ常に動画が有利(容量/画質)。ただし自動再生配慮は必須。
31回だけ再生して止めたい。
loop を外し、ended イベントでポスターへ戻す。

gazou-compressor.jp 編集部

画像圧縮・変換・背景除去などの実践テクニックと、Webで“速く・軽く・崩さない”ためのノウハウを発信しています。

関連記事

トピック/更新日の近いコンテンツ