useVisualViewport
useVisualViewport は、Visual Viewport の変化を追跡する React フックです。 モバイル WebView で実際に見えている領域を返します。この領域は、キーボードの表示やユーザーのズーム、スクロールによって変化します。
インターフェース
ts
function useVisualViewport(): { viewport: VisualViewportState | null };パラメータ
この関数はパラメータを受け取りません。
戻り値
- { viewport: VisualViewportState | null }
Visual Viewport の状態を含むオブジェクト。
- viewportVisualViewportState | null
Visual Viewport の状態オブジェクト。非対応の環境(SSR、または Visual Viewport API 非対応のブラウザー)では
nullです。 - viewport.widthnumber
ビューポートの幅(ピクセル単位)。
- viewport.heightnumber
ビューポートの高さ(ピクセル単位)。
- viewport.offsetLeftnumber
レイアウトビューポートを基準とした、ビューポート左端のオフセット(ピクセル単位)。通常、水平スクロールやパン操作がなければ 0 です。
- viewport.offsetTopnumber
レイアウトビューポートを基準とした、ビューポート上端のオフセット(ピクセル単位)。iOS ではキーボードが表示されると負の値になります(例:-300px はキーボードの高さが 300px であることを表します)。そのため、キーボードの高さには
-offsetTopを使ってください。Android では通常 0 のままです。 - viewport.scalenumber
ピンチズームの倍率。1.0 はズームなし、1.0 より大きい値は拡大、1.0 より小さい値は縮小を表します(縮小はまれで、ビューポートの設定によります)。
- viewportVisualViewportState | null
使用例
tsx
function CustomLayout() {
const { viewport } = useVisualViewport();
// 必ず最初に null かどうかを確認します
if (!viewport) {
return <div>Visual Viewport not supported</div>;
}
const { width, height, offsetTop, scale } = viewport;
// ユーザーがズームインしたときにフローティング UI を非表示にします
const showFloatingUI = scale <= 1.3;
return (
<div style={{ height }}>
{showFloatingUI && <FloatingButton />}
Viewport-aware content
</div>
);
}ズームを検出する
tsx
const { viewport } = useVisualViewport();
if (viewport && viewport.scale > 1.3) {
// ユーザーがズームインしたときにフローティング UI を非表示にします
setShowFloatingButton(false);
}注意点
- SSR の安全性:サーバーサイドレンダリング時や Visual Viewport API 非対応のブラウザーでは、
viewportはnullです。プロパティを読み取る前に、必ずnullかどうかを確認してください。 - ブラウザーの対応:Visual Viewport API は、モダンなモバイルブラウザーで利用できます。API がない環境では、このフックは
nullを返します。 - パフォーマンス:更新を React の
startTransitionでラップするため、ビューポートの変化が緊急のレンダリングを妨げません。 - よりシンプルな代替手段:キーボードの高さだけが必要な場合は、よりシンプルな API の
useKeyboardHeight()を使ってください。 - プラットフォームによる違い:iOS ではキーボードが表示されると
offsetTopが負の値になります。Android では通常 0 のままです。 - ユースケース:キーボードの検出、ピンチズームへの対応、ビューポートに応じたレイアウトの構築、ズーム倍率に応じた UI の表示切り替え。