この記事について この記事は、生成AIを活用した自動生成フローで作成しています。 MDNのResizeObserver公式解説を確認し、架空のカードの幅を変えてレイアウトの切替を学ぶ教材を作成しました。JavaScript構文と幅判定ロジックは確認しましたが、実ブラウザ・WordPress表示は未確認です。
検証ステータス:🧪 構文・幅判定ロジック確認済み/実ブラウザ未確認
「画面の幅ではなく、カードを置いた箱そのものの幅で表示を変えたい」。そんな場面で使えるのがブラウザ標準のResizeObserverです。箱の幅を300pxから520pxへ変え、カードの並び方と実測数値が変わる様子を観察します。
| 項目 | この教材の条件 |
|---|---|
| 対象 | ResizeObserver対応ブラウザ |
| 料金・認証 | 無料・ログイン不要 |
| 外部ライブラリ | なし |
| データ | 架空のタスクカード |
| 検証 | V8構文・幅判定のみ |
| 未確認 | ブラウザ、Pages、WordPress |
まず試す:箱の幅でカードを切り替える
ライブデモを開く(公開ページの到達とブラウザ動作は未確認)/GitHubサンプルとREADME
デモを開き、「300px」を押します。カードが縦並びになり、実測幅が表示される想定です。
「520px」を押します。画面に十分な幅があれば、横並びへ切り替わります。
「観察停止」を押して幅を変えます。実測表示の更新が止まることを確認し、「観察再開」で戻します。
操作はデモの冒頭に配置しています。もし404や空白が出たら、後半の「自分のPCで動かす」を参照してください。デモURLはリポジトリの公開パス規則に沿ったもので、到達確認済みURLではありません。
操作後はここを見る:指定幅と実測幅の違い
| 操作 | 期待する表示 |
|---|---|
| 300px | 縦並び |
| 520px | 横並び(十分広い画面) |
| 観察停止 | 数値の更新が止まる |
| 観察再開 | 現在の幅を再取得 |
カードの外枠には左右2pxずつの線があります。計測対象のcontent boxはその線を含まないため、指定幅300pxでも実測は約296pxになる設計です。520pxなら約516pxを想定します。これらは期待値であり、ブラウザ実測値ではありません。
スマートフォンなどで表示領域が狭い場合、CSSのmax-width:100%により箱の幅は指定値より小さくなります。そこで、520pxを選んでも横並びにならないことがあります。これは不具合と決めつけず、表示された実測幅を先に確認します。
この実験の面白さは、画面全体を拡大・縮小しなくても、カードを入れた箱だけの変化を検知できる点です。ダッシュボードの左右パネルや埋め込みウィジェットを想像すると、用途が見えてきます。
なぜ動く?:ウィンドウ幅ではなく要素を監視する
window.resizeは主にウィンドウの大きさの変更を知るイベントです。一方、ResizeObserverは指定した要素のサイズが変わったときに通知します。隣のパネルが開閉して箱が狭くなる場合など、ウィンドウの大きさが同じでも変化を扱えます。
flowchart TD
A["幅ボタン・スライダー"] --> B["箱の幅を変更"]
B --> C["ResizeObserverが通知"]
C --> D["content boxの幅を読む"]
D --> E["360px未満: 縦 / 以上: 横"]
重要なのは、監視対象の幅を通知の中で何度も増減させないことです。監視したサイズに応じて同じ要素の幅を変え続けると、ResizeObserverの循環通知が発生する場合があります。本教材では監視対象の幅はボタンやスライダーだけで変更し、通知内では内側のカード配置と文字表示だけを更新します。
核心部分は次の短いコードです。
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const width = entry.contentRect.width;
const mode = width < 360 ? "compact" : "wide";
entry.target.dataset.layout = mode;
}
});
observer.observe(document.getElementById("stage"));
上記は仕組みを説明する抜粋です。完成版ではcontentBoxSizeを優先して幅を読み、互換性のためcontentRect.widthへフォールバックします。ボタンのイベント、観察停止・再開、pagehide時のdisconnect()も完成版にあります。
1か所変えてみる:境界値を360から420へ
完成版app.jsのmodeFor関数にある360だけを420へ変更します。ほかの値は変えません。例えば実測幅400px付近なら、変更前は横並び、変更後は縦並びになると予想できます。
| 実測幅 | 境界360 | 境界420 |
|---|---|---|
| 300px | 縦 | 縦 |
| 400px | 横 | 縦 |
| 520px | 横 | 横 |
指定幅ではなく実測幅で判定する点が大切です。狭い画面では実測400pxの条件を作れないこともあります。広い画面で試すか、開発者ツールで表示領域を調整してください。実験後は360に戻します。
自分のPCで動かす
固定コミットのREADMEからindex.htmlとapp.jsを確認し、両方を同じフォルダへ保存します。index.htmlをブラウザで開き、300pxと520pxのボタンを押します。外部CDNやビルドツールは使用しません。ファイルを開いただけでネットワークへデータを送るコードもありません。
画面のHTML/CSSとJavaScriptは別ファイルです。ブログ本文へ長い完成コードを貼らず、GitHub側で安全に試せる形にしています。Webページが表示されてもブラウザ実機での成功を記録したことにはなりません。
うまく動かないとき
| 症状 | 確認する場所 |
|---|---|
| 画面が白い | app.jsの配置、Console |
| 未対応と出る | ResizeObserver対応状況 |
| 横並びにならない | 指定幅でなく実測幅 |
| 数値が変わらない | 観察停止中か |
| ループ警告 | 監視対象の幅を通知内で変更していないか |
特にResizeObserver loop completed with undelivered notificationsという警告は、ブラウザが循環的なリサイズ通知を抑制している可能性を示します。通知を受けるたびに同じ箱を拡大する実装は避け、状態の変更が本当に必要かを点検してください。
観察停止はunobserve()、再開はobserve()、ページを離れるときの後始末はdisconnect()を使います。実際のWebアプリでも、不要になった監視を残さない設計が大切です。
仕事・学習で使うなら
例えば、架空の業務ダッシュボードで「タスク一覧」と「詳細」の2つのパネルを並べる場合を考えます。詳細パネルを開くと一覧側の幅が狭くなるため、画面全体の幅が変わらなくても一覧カードを縦並びにしたいことがあります。今回の仕組みは、要素の幅を測って表示モードを切り替える最小例になります。
ただし、単にCSSのレイアウトを切り替えるだけなら、コンテナクエリなどCSSだけで実現できる場合があります。JavaScriptで数値表示や処理の切替が必要なときにResizeObserverを検討し、使わなくて済むならCSSを優先するのも設計判断です。
本教材では個人情報・社内データ・位置情報・音声・外部APIキーを使いません。実業務へ組み込む前には、対象ブラウザ、キーボード操作、画面読み上げ、狭い端末、印刷/PDFのレイアウトを実際に確認してください。デモ専用のCSSをWordPress本文へ埋め込む必要はありません。
サイズの判定を間違えないための追加実験
ResizeObserverが通知するのは、画面全体の横幅ではなく監視対象の要素に関するサイズです。ブラウザのウィンドウ幅が変わらなくても、サイドバーが開いたり親要素の幅が変わったりすれば、カード幅が変わる場合があります。逆にウィンドウを広げても要素の最大幅が固定されていれば、観測値が変わらない場合があります。実験では画面幅と監視対象の幅を別にメモし、どちらが切り替えの判断材料なのか確かめてください。
CSSのpaddingやborderがあると、画面で見た外側の幅と、取得した内容領域の幅が一致しないことがあります。contentRect、borderBoxSizeなどの意味を混同しないようにします。切替境界を調べるときは、監視している幅がどのボックスの値なのかを確認し、想定の300pxや520pxと数値が少しずれても即座にバグと判断しないでください。
監視のコールバック内で対象要素のサイズを直接変えると、新たなサイズ変更が起きて通知が続く設計になることがあります。自動で何度も切り替わる場合は、幅を変える側と観測する側を切り分けます。業務画面のカードへ応用するときは、画面全体の横幅だけに依存するより、実際に利用できるカードの幅を確認した方が説明しやすい場面があります。固定値と実測値を併記すると利用者にも違いが伝わります。
公式資料
MDN:ResizeObserver — 要素サイズの監視とループ警告(2026-11-01確認)
MDN:ResizeObserverEntry — contentBoxSizeとcontentRectの違い(2026-11-01確認)
MDN:observe() — 監視開始とbox指定(2026-11-01確認)
GitHubサンプル
検証範囲: JavaScript構文と純粋な幅判定6条件、GitHub上のソース3ファイルの保存・読戻しを確認。ブラウザ操作、Pages到達、WordPressの青い引用枠、アイキャッチ、スマホ表示、A4/PDF印刷は未確認です。アイキャッチ画像は未制作・未登録であり、存在しないメディアIDを指定していません。
