JavaScript Resize Observer 元素大小觀察器

在傳統網頁開發中,如果我們要開發「響應式」佈局,通常會監聽 windowresize 事件。但 window.onresize 只能告訴我們瀏覽器視窗變大了或縮小了,卻無法直接偵測「特定 DOM 元素」的大小變化。

Resize Observer API 完美解決了這個問題。它讓你可以精確觀察單一元素的大小變化,無論是因為視窗縮放、CSS 改變、或是動態插入內容所引起的尺寸變動。

為什麼需要 Resize Observer?

  1. 元件導向 (Component-based): 當前的網頁開發趨向元件化,一個側邊欄的收合可能會改變主內容區域的大小,但此時 window 的尺寸可能完全沒變,導致傳統的媒體查詢(Media Queries)或 window.resize 失效。
  2. 效能優化: 它比監聽 window.resize 並不斷執行 getBoundingClientRect() 更高效。它會異步地批次通知尺寸變化,避免造成佈局抖動(Layout Thrashing)。
  3. 解決 Container Queries 的痛點: 在 CSS Container Queries 完全普及前,這是實現「根據容器大小決定樣式」的最佳 JavaScript 方案。

基本用法

// 1. 建立觀察器實例
const ro = new ResizeObserver((entries) => {
  for (let entry of entries) {
    // entry.contentRect 包含了元素的尺寸資訊
    const { width, height } = entry.contentRect;
    console.log(`元素的新尺寸:寬 ${width}px, 高 ${height}px`);

    // 實務應用:根據寬度切換 Class
    if (width < 500) {
      entry.target.classList.add('mobile-mode');
    } else {
      entry.target.classList.remove('mobile-mode');
    }
  }
});

// 2. 開始觀察特定元素
const myElement = document.querySelector('#responsive-box');
ro.observe(myElement);

entry.contentRect 的屬性

回呼函式提供的 contentRect 物件包含以下屬性:

  • width, height: 元素的內容寬度與高度。
  • top, left: 內容區域距離元素內邊界的偏移。
  • right, bottom: 類似 CSS 的坐標值。

實際應用範例:響應式圖表

如果您開發的是資料圖表(如使用 D3.js 或 ECharts),圖表通常需要根據容器大小重新繪製(Redraw)。

const chartContainer = document.querySelector('.chart-wrapper');

const chartObserver = new ResizeObserver((entries) => {
  // 由於 resize 事件可能觸發頻繁,通常會加上 debounce (防抖) 處理
  requestAnimationFrame(() => {
    myChart.resize(); // 假設這是圖表庫提供的重繪方法
    console.log('圖表已根據容器大小重新調整');
  });
});

chartObserver.observe(chartContainer);

與 window.resize 的比較

特性window.onresizeResize Observer
觀察對象僅限整個視窗 (Viewport)任何特定 DOM 元素
效能頻繁觸發,容易造成阻塞異步、由瀏覽器優化批次通知
細微度高,可針對單一元件
觸發原因視窗縮放視窗縮放、CSS 改變、內容變動、甚至隱藏切換

瀏覽器支援度

這是一項成熟的技術,目前所有的主流瀏覽器(Chrome, Firefox, Safari, Edge)皆已完整支援。

總結

Resize Observer 是開發「真正響應式元件」的關鍵。它打破了傳統以視窗為中心的思維,讓元件能夠根據自身所在的上下文容器(Container)靈活調整外觀與行為。

相關閱讀: