JavaScript Resize Observer 元素大小觀察器
在傳統網頁開發中,如果我們要開發「響應式」佈局,通常會監聽 window 的 resize 事件。但 window.onresize 只能告訴我們瀏覽器視窗變大了或縮小了,卻無法直接偵測「特定 DOM 元素」的大小變化。
Resize Observer API 完美解決了這個問題。它讓你可以精確觀察單一元素的大小變化,無論是因為視窗縮放、CSS 改變、或是動態插入內容所引起的尺寸變動。
為什麼需要 Resize Observer?
- 元件導向 (Component-based): 當前的網頁開發趨向元件化,一個側邊欄的收合可能會改變主內容區域的大小,但此時
window的尺寸可能完全沒變,導致傳統的媒體查詢(Media Queries)或window.resize失效。 - 效能優化: 它比監聽
window.resize並不斷執行getBoundingClientRect()更高效。它會異步地批次通知尺寸變化,避免造成佈局抖動(Layout Thrashing)。 - 解決 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.onresize | Resize Observer |
|---|---|---|
| 觀察對象 | 僅限整個視窗 (Viewport) | 任何特定 DOM 元素 |
| 效能 | 頻繁觸發,容易造成阻塞 | 異步、由瀏覽器優化批次通知 |
| 細微度 | 低 | 高,可針對單一元件 |
| 觸發原因 | 視窗縮放 | 視窗縮放、CSS 改變、內容變動、甚至隱藏切換 |
瀏覽器支援度
這是一項成熟的技術,目前所有的主流瀏覽器(Chrome, Firefox, Safari, Edge)皆已完整支援。
總結
Resize Observer 是開發「真正響應式元件」的關鍵。它打破了傳統以視窗為中心的思維,讓元件能夠根據自身所在的上下文容器(Container)靈活調整外觀與行為。
相關閱讀: