ResizeObserver

Baseline Widely available

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

ResizeObserver インターフェイスは、要素 (Element) のコンテンツまたは境界ボックス、または SVGElement のバウンディングボックスの大きさが変化したことを報告します。

メモ: コンテンツボックスは、コンテンツを配置できるボックスです。つまり、境界ボックスからパディングを引いたものです。境界とパディングの説明はボックスモデルを参照してください。

コンストラクター

ResizeObserver()

新しい ResizeObserver オブジェクトを作成して返します。

インスタンスプロパティ

なし。

インスタンスメソッド

ResizeObserver.disconnect()

特定のオブザーバーの監視対象の Element をすべて監視解除します。

ResizeObserver.observe()

指定された Element の監視を開始します。

ResizeObserver.unobserve()

指定された Element の監視を終了します。

resize-observer-text.htmlソースを参照)の例では、スライダーの値が変更され、それを含む <div> の幅が変更されると、リサイズオブザーバーを使用してヘッダーと段落の font-size を変更します。これは、ビューポートに影響がない要素のサイズの変化にも応答することができることを示しています。

また、オブザーバーをオフやオンにするためのチェックボックスも用意しています。オフにすると、 <div> の幅が変化してもテキストは変化しません。

JavaScript は次のようになります。

js
const h1Elem = document.querySelector("h1");
const pElem = document.querySelector("p");
const divElem = document.querySelector("body > div");
const slider = document.querySelector('input[type="range"]');
const checkbox = document.querySelector('input[type="checkbox"]');

divElem.style.width = "600px";

slider.addEventListener("input", () => {
  divElem.style.width = `${slider.value}px`;
});

const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    if (entry.contentBoxSize) {
      const contentBoxSize = entry.contentBoxSize[0];
      h1Elem.style.fontSize = `${Math.max(
        1.5,
        contentBoxSize.inlineSize / 200,
      )}rem`;
      pElem.style.fontSize = `${Math.max(
        1,
        contentBoxSize.inlineSize / 600,
      )}rem`;
    } else {
      h1Elem.style.fontSize = `${Math.max(
        1.5,
        entry.contentRect.width / 200,
      )}rem`;
      pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
    }
  }

  console.log("Size changed");
});

resizeObserver.observe(divElem);

checkbox.addEventListener("change", () => {
  if (checkbox.checked) {
    resizeObserver.observe(divElem);
  } else {
    resizeObserver.unobserve(divElem);
  }
});

監視エラー

仕様に従う実装では、描画前(つまり、フレームがユーザーに表示される前)にリサイズイベントを呼び出します。リサイズ イベントがあった場合、スタイルとレイアウトが再評価され、さらにリサイズイベントが発生する可能性があります。循環的な依存関係による無限ループは、それぞれの反復処理中に DOM のより深い要素のみを処理することで対処します。この条件を満たさないリサイズイベントは次の描画に延期され、エラーイベントが Window オブジェクトに定義されたメッセージ文字列とともに発行されます。

ResizeObserver loop completed with undelivered notifications.

これはユーザーエージェントのロックを防ぐだけで、無限ループそのものを防ぐわけではないことに注意してください。例えば、次の例では divElem の幅が無限に広がり、コンソールに上記のようなエラーメッセージが毎フレーム発生します。

js
const divElem = document.querySelector("body > div");

const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    entry.target.style.width = entry.contentBoxSize[0].inlineSize + 10 + "px";
  }
});

window.addEventListener("error", function (e) {
  console.error(e.message);
});

エラーイベントがいつまでも発行されない限り、リサイズオブザーバーは決定し、安定した、おそらく正しいレイアウトを生成します。しかし、訪問者は、単一のフレームで起こるはずの一連の変更が、複数のフレームにわたって起こるため、壊れたレイアウトがフラッシュして見えるかもしれません。

仕様書

Specification
Resize Observer
# resize-observer-interface

ブラウザーの互換性

BCD tables only load in the browser

関連情報