トラブルシューティング

iOS Safari 特有の問題、動画の再生、フルスクリーン、キーボード操作に関する対処法です。

iOS Safari

ビューポートが画面いっぱいにならない/下に黒い余白が出る

Safari の折りたたみ式アドレスバーのせいで、100vh は見えている領域より高くなります。100dvh を使ってください:

css
.slider-container {
  height: 100dvh; /* not 100vh */
}

横スクロールが出る/コンテンツがはみ出す

iOS では 100vw にスクロールバーの幅が含まれ、コンテンツが端からはみ出します。100% を使い、横方向のはみ出しを止めてください:

css
html, body {
  overflow-x: hidden;
}

.slider-container {
  width: 100%; /* not 100vw */
}

引っ張って更新/ラバーバンドのバウンス

Safari の「引っ張って更新」と弾むスクロールは、縦方向のスワイプジェスチャーとぶつかります。html, body に overscroll-behavior: none を付けては いけません。通常のページスクロールが効かなくなります。ReelPlayerOverlay、LightboxOverlay、StoriesPlayerOverlay は自分のコンテナーでこれを処理しています。独自のレイアウトでは、範囲を限定して指定してください:

css
.slider-container {
  overscroll-behavior: none;
}

下方向の SwipeToClose で起きる特殊なケース。 direction="down" を指定した SwipeToClose(lightbox、ストーリープレイヤー、独自のオーバーレイ)は、iOS Safari で横取りされます。ラッパーがタッチを受け取る前に、ブラウザーがドキュメントのレベルで「引っ張って更新」を発火させるためです。オーバーレイは body のスクロールを止めますが、ルートでの縦方向のパン操作はブラウザーが握ったままです。オーバーレイが開いているあいだだけ <html> に overscroll-behavior-y: contain を指定し、閉じるときに元に戻してください:

tsx
useEffect(() => {
  if (!isOpen) return;
  const html = document.documentElement;
  const prev = html.style.overscrollBehaviorY;
  html.style.overscrollBehaviorY = 'contain';
  return () => {
    html.style.overscrollBehaviorY = prev;
  };
}, [isOpen]);

ピンチズームがジェスチャーを邪魔する

ズームを無効にして、スワイプ中にピンチやダブルタップが発火しないようにします:

html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />

viewport-fit=cover を指定すると、レイアウトが Dynamic Island やノッチのセーフエリアまで広がります。

キーボードを閉じたあとにレイアウトが崩れる

Safari では、キーボードを閉じたあともビューポートが縮んだままになることがあります。blur のタイミングで強制的にリセットしてください:

tsx
// React
<input
  onBlur={() => {
    window.scrollTo(0, 0);
    apiRef.current?.adjust();
  }}
/>

// Angular
(blur)="onInputBlur()"

onInputBlur() {
  window.scrollTo(0, 0);
  this.reelApi?.adjust();
}

全般

スライドが 0×0 のサイズで描画される

size プロップがない場合、スライダーは ResizeObserver でコンテナーの寸法を読み取ります。CSS で高さが決まっていないコンテナーは 0×0 と計測され、何も描画されません。size を渡すか、コンテナーに寸法を与えてください:

css
/* The parent must have a height for auto-sizing to work */
.slider-container {
  width: 100%;
  height: 100dvh;
}

動画

動画が自動再生されない

ブラウザーは音声付きの自動再生をブロックします。ReelKit はすべての動画要素に muted と playsInline を設定しています。動画はミュートで始まり、ユーザーはタップしたあとでサウンドボタンからミュートを解除します。独自のスライドでこれらの属性を上書きしていないか確認してください。

動画のサムネイル/フレームキャプチャーが真っ白になる

フレームキャプチャーは動画を <canvas> に描画します。別オリジンの動画は canvas を汚染するため、描画は何も言わずに失敗します。動画を配信する CDN は CORS ヘッダーを返す必要があります:

text
Access-Control-Allow-Origin: *

ReelKit はデフォルトで crossOrigin="anonymous" を設定します。独自の動画要素を使う場合は、自分で追加してください。

フルスクリーン

Safari でフルスクリーンボタンが何もしない

ReelKit は Safari で Fullscreen API を無効にしています。iOS Safari ではフルスクリーンにできるのが <video> 要素に限られます。デスクトップの Safari では、フルスクリーン中に position: fixed のオーバーレイが崩れ、要素がスタッキングコンテキストを失ったり消えたりします。Safari では requestFullscreen() は何もせずに完了します。

キーボード操作

onNavKeyPress を渡したら矢印キーで移動しなくなった

onNavKeyPress はデフォルトのキーボード操作を 置き換えます。ReelKit は next()/prev() を呼ぶのをやめ、制御をあなたに渡します。自分で呼んでください:

tsx
<Reel
  onNavKeyPress={(increment) => {
    // Your custom logic here
    console.log('Nav key:', increment);
    // You must trigger navigation yourself:
    apiRef.current?.[increment === 1 ? 'next' : 'prev']();
  }}
/>

Escape キーでオーバーレイが閉じない

キーボードコントローラーが扱うのは矢印キーだけです。ReelPlayerOverlay と LightboxOverlay は Escape を別に監視しています。独自のオーバーレイを作る場合は、onClose の中で Escape の処理を自分で追加してください。