VisualViewport

Baseline Widely available *

This feature is well established and works across many devices and browser versions. It’s been available across browsers since August 2021.

* Some parts of this feature may have varying levels of support.

VisualViewport視覚的ビューポート API のインターフェイスで、指定されたウィンドウの視覚的ビューポートを表します。 iframe があるページでは、コンテナーページだけでなく、それぞれの iframe にも固有のウィンドウオブジェクトが存在します。ページ上の各ウィンドウには、そのウィンドウに関連付けられたプロパティを表す固有の VisualViewport が存在します。

ウィンドウの視覚的ビューポートは、 Window.visualViewport を使用して取得することができます。

メモ: レイアウトビューポートとは異なる視覚的ビューポート持つのは最上位のウィンドウのみです。したがって、一般的には最上位のウィンドウの VisualViewport オブジェクトのみが使用されます。 <iframe> の場合、 VisualViewport.width のような視覚的ビューポートのメトリクスは、常に document.documentElement.clientWidth などのレイアウトビューポートのメトリクスに対応します。

EventTarget VisualViewport

インスタンスプロパティ

親インターフェイスである EventTarget から継承したプロパティもあります。

VisualViewport.offsetLeft 読取専用

視覚的ビューポートの左端のオフセットを、レイアウトビューポートの左端からの CSS ピクセル数で返します。

VisualViewport.offsetTop 読取専用

視覚的ビューポートの上端のオフセットを、レイアウトビューポートの上端からの CSS ピクセルで返します。

VisualViewport.pageLeft 読取専用

視覚的ビューポートの x 座標を、初期包含ブロックの上端の原点からの相対 CSS ピクセル数で返します。

VisualViewport.pageTop 読取専用

視覚的ビューポートの y 座標を、初期包含ブロックの上端の原点からの相対 CSS ピクセル数で返します。

VisualViewport.width 読取専用

視覚的ビューポートの幅を、 CSS ピクセル単位で返します。

VisualViewport.height 読取専用

視覚的ビューポートの幅を、 CSS ピクセル単位で返します。

VisualViewport.scale 読取専用

視覚ビューポートに適用されたピンチズームの倍率を返します。

インスタンスメソッド

親インターフェイスである EventTarget から継承したメソッドもあります。

イベント

これらのイベントは、 addEventListener() を使用するか、イベントリスナーをこのインターフェイスの関連する onイベント名 プロパティに代入するかして待ち受けします。

resize

視覚的ビューポートがリサイズされると発行されます。 onresize プロパティからも利用できます。

scroll

視覚的ビューポートがスクロールされると発行されます。 onscroll プロパティからも利用できます。

scrollend

視覚的ビューポートでのスクロール操作が終了すると発行されます。 onscrollend プロパティからも利用できます。

ズーム時に重なったボックスを非表示にする

この例では、 Visual Viewport の README から引用し、ユーザーがズームインした際に、オーバーレイされたボックス(例えば広告を含む)を非表示にするコードを少し書く方法を示しています。これは、ページをズームインする際のユーザーの使い勝手を向上させる良い方法です。ライブサンプルも利用できます。

js
const bottomBar = document.getElementById("bottom-bar");
const viewport = window.visualViewport;

function resizeHandler() {
  bottomBar.style.display = viewport.scale > 1.3 ? "none" : "block";
}

window.visualViewport.addEventListener("resize", resizeHandler);

位置のシミュレーション: device-fixed

この例も、 Visual Viewport の README から引用したものですが、この API を使用して position: device-fixed という、要素を視覚的ビューポートに固定する方法を示しています。ライブサンプルも利用できます。

js
const bottomBar = document.getElementById("bottom-bar");
const viewport = window.visualViewport;
function viewportHandler() {
  const layoutViewport = document.getElementById("layoutViewport");

  // バーは position: fixed であるため、レイアウトビューポートの原点から
  // 視覚的ビューポートのオフセットを差し引く必要があります。
  const offsetLeft = viewport.offsetLeft;
  const offsetTop =
    viewport.height -
    layoutViewport.getBoundingClientRect().height +
    viewport.offsetTop;

  // これは style.left と style.top を設定することで、
  // width: 100% と同じことができます。
  bottomBar.style.transform = `translate(${offsetLeft}px, ${offsetTop}px) scale(${
    1 / viewport.scale
  })`;
}
window.visualViewport.addEventListener("scroll", viewportHandler);
window.visualViewport.addEventListener("resize", viewportHandler);

メモ: このテクニックは慎重に使用しましょう。このように position: device-fixed を模倣すると、修正された要素がスクロール時にちらつくことがあります。

仕様書

Specification
CSSOM View Module
# the-visualviewport-interface

ブラウザーの互換性

BCD tables only load in the browser

関連情報

  • Web Viewports Explainer — 視覚的ビューポートとレイアウトビューポートの違いなど、ウェブビューポートの概念に関する有益な説明が記載されています。