jQuery / メソッド / .resize() - ウィンドウサイズの変更を処理する

ブラウザーのウィンドウサイズ変更には$(window).on("resize", 処理関数)を使います。短縮形.resize(処理関数)はjQuery 3.3から非推奨なので、新規コードは.on()で書きます。初期画面にも同じ処理が必要なら変更を待たずに更新関数を一度呼びます。

resizeイベントと短縮形の違い

jQueryのresizeイベントはwindowへ処理を登録します。.resize()短縮形の非推奨は、イベント自体を使わないという意味ではありません。確認した完全版3.7.1・4.0.0にも短縮形はありますが、.on("resize", …)なら登録と解除範囲を明確にできます。

ネイティブwindow resizeイベントはバブリングせず、divの幅変更でそのdivに自動発生するものでもありません。要素自身の寸法にはResizeObserverを検討します。ウィンドウ操作中は複数回通知される場合があるため、正確な回数を前提にしません。

初期表示・デバウンス・解除を含む完全な例

全コードをUTF-8のresize-demo.htmlとして保存し、ブラウザーで開きます。コンテンツ配信ネットワーク(CDN)の公式jQueryファイル4.0.0を読むインターネット接続が必要で、インストールは不要です。操作はWindowsのEdgeと3.7.1・4.0.0で実行し、ビューポート寸法を変更しました。

デバウンスは連続通知の前のタイマーを取り消し、最後の通知から150ms後に更新する方法です。ブラウザーの予約状況で実行はさらに遅れる場合があります。600 CSSピクセルを境にnarrow・wideを表示し、サンプルの枠はCSSメディアクエリーで変更します。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Window resize with debounce and cleanup</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button { font: inherit; margin: 4px; max-width: 100%; }
    #sample { padding: 16px; background: #edf9f6; border: 1px solid teal; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
    @media (min-width: 600px) { #sample { border-width: 3px; } }
  </style>
</head>
<body>
  <h1>Observe window resize</h1>
  <button type="button" id="trigger">Trigger resize notification</button>
  <button type="button" id="stop">Stop listener</button>
  <button type="button" id="start">Start listener</button>
  <button type="button" id="reset">Reset counters</button>
  <div id="sample">Resize the browser or responsive preview.</div>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      let timer = null, active = false, events = 0, renders = 0;
      function render() {
        renders++;
        const width = window.innerWidth;
        const height = window.innerHeight;
        $("#result").text(`viewport=${width} x ${height}\nmode=${width < 600 ? "narrow" : "wide"}\nlistener=${active ? "on" : "off"}\nresize events=${events}\nrenders=${renders}`);
      }
      function changed() {
        events++;
        clearTimeout(timer);
        timer = setTimeout(function () { timer = null; render(); }, 150);
      }
      function detach() {
        $(window).off("resize.windowLesson");
        clearTimeout(timer); timer = null; active = false;
      }
      function attach() {
        detach();
        $(window).on("resize.windowLesson", changed);
        active = true;
        render();
      }
      $("#trigger").on("click", function () { $(window).trigger("resize"); });
      $("#stop").on("click", function () { detach(); render(); });
      $("#start").on("click", attach);
      $("#reset").on("click", function () { detach(); events = 0; renders = 0; attach(); });
      attach();
    });
  </script>
</body>
</html>

次は390×844 CSSピクセルの初期結果です。自分の画面寸法は異なり、幅600以上はwideです。resize events=0なのにrenders=1なのは初期関数を直接呼んだからです。

viewport=390 x 844
mode=narrow
listener=on
resize events=0
renders=1
  1. ウィンドウや開発者ツールのレスポンシブ表示を変更します。操作後、viewportが最終寸法になるか確認します。resize eventsは通知数、rendersは更新数です。
  2. Trigger resize notificationは通知のみです。イベント・遅延更新数は増えてもウィンドウ寸法は変わりません。
  3. Stop listenerでlistener=offになり、その後のサイズ変更でも出力は止まります。予約タイマーも取り消し、遅れて更新されません。
  4. Start listenerは現在寸法を再取得します。旧処理を解除して登録するため繰り返しても自分の処理は一つです。
  5. Reset countersは現在寸法でイベント0・更新1に戻し再開します。ウィンドウを390×844に戻す操作ではありません。

処理停止と実寸法の復元は区別します。同じ寸法で通知ボタンだけ押すと、イベントと実サイズ変更の違いが分かります。同期通知三つの検証ではイベント3回・遅延更新1回でしたが、実マウス操作の回数をこの数に固定しません。

重複登録と遅延処理の整理

resize.windowLessonという名前空間で自分の処理を区別します。.off("resize.windowLesson")は、他のresize処理も消す.off("resize")と範囲が違います。同じwindowを使う複数部品では重複しない名前と寿命管理が必要です。

イベントを解除しても予約済みsetTimeoutは消えません。detach()はclearTimeout(timer)も行います。attach()が旧登録と予約を先に解除し、Resetも同じ経路を再利用します。部品削除やページ遷移では両方を整理します。

既存コードの.resize(handler)は登録、引数なし.resize()は通知です。次のConsole例は独立オブジェクトで旧短縮形を確認し、実ウィンドウや主例のカウンターを変えません。新コードは前述の.on()・.trigger()を使います。

const $target = $({});
let calls = 0;
$target.resize(function () { calls++; });
$target.resize();
console.log(`legacy shorthand calls=${calls}`);
$target.off("resize");
legacy shorthand calls=1

resizeで解決すべき処理か判断する

単純な列配置・色・枠はCSSメディアクエリーで扱えます。JavaScriptで幅取得とスタイル変更を繰り返す前にCSSで足りるか確認します。例も枠はCSS、通知数と状態はJavaScriptです。

デバウンスは操作中の各段階でなく最終寸法を処理します。連続反応が必要な作業には意図的な遅延が不便な場合があるので、必要なタイミングを先に決めます。全通知でサーバー要求などの重い処理を行ったり、同じ出力をDOM(Document Object Model、文書オブジェクトモデル)へ追加し続けたりしません。

ウィンドウが同じでもサイドバー・フォント・内容で要素寸法は変わります。window resizeだけでは全変化を検出できません。ResizeObserverでは測るボックスと変更対象を区別し、コールバックで観察対象の寸法を繰り返し変える構造を避けます。CSSピクセルのウィンドウ寸法は物理ディスプレイ解像度とも別です。