ResizeObserver 是 HTML5 原生 API,用于高效精准监听元素内容区尺寸变化,基于 contentRect 获取宽高,不触发重排,兼容现代浏览器(IE 不支持)。

ResizeObserver 是 HTML5 提供的原生 API,用于高效、精准地监听元素尺寸变化,无需轮询或依赖窗口 resize 事件。它天然支持单个元素监听,响应及时、性能友好,且能捕获 box-sizing(content-box / border-box)下真实内容区域的变化。
核心监听逻辑:基于 contentRect 的精确尺寸获取
ResizeObserver 回调中传入的 entries 数组每个项都包含 contentRect 属性——这是最可靠的尺寸数据源,代表元素内容区(content box)的宽高与偏移,不受 padding/border 影响,也不受 transform 干扰。相比 getBoundingClientRect(),它不触发重排,且在元素隐藏、缩放、CSS 动画过程中仍保持稳定。
- 优先读取
entry.contentRect.width和entry.contentRect.height,而非boundingClientRect或target.offsetWidth - 若需监听 border-box 尺寸(含 padding + border),可手动计算:
contentRect.width + parseFloat(getComputedStyle(target).paddingLeft) + parseFloat(getComputedStyle(target).paddingRight) + ... - 注意:contentRect 的 left/top 是相对于父容器(非视口),通常仅需宽高,无需坐标时可忽略
单元素监听的正确初始化方式
监听单个元素时,应直接传入该 DOM 节点,并在回调中校验 entry.target 是否为预期元素(避免因复用 observer 导致误判)。同时建议在观察前确保元素已挂载到文档中。
- 创建 observer 实例时使用箭头函数或绑定 this,避免回调中 this 指向丢失
- 调用
observer.observe(targetElement)即可开始监听;无需反复调用,一次注册即持续生效 - 若元素可能被销毁,应在移除前调用
observer.unobserve(targetElement),防止内存泄漏
规避常见陷阱:时机、重复触发与兼容性
ResizeObserver 的触发时机是浏览器布局后、绘制前,因此能捕捉到 CSS Flex/Grid 重排、visibility 变化、甚至 display: none → block 的首次尺寸。但它不会响应 scroll、opacity、transform(除非影响布局)等纯渲染属性变化。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
- 避免在回调中直接修改被监听元素的尺寸样式(如动态改 width),否则可能引发无限回调循环
- 如需去抖,不要用 setTimeout,而应利用 ResizeObserver 自身的批处理机制:它会将同一帧内多次尺寸变更合并为一次回调
- 兼容性方面:现代浏览器全覆盖(Chrome 64+、Firefox 69+、Safari 13.1+、Edge 79+);IE 完全不支持,需用 resize 事件 + getBoundingClientRect 模拟(仅作降级)
一个轻量实用示例
监听一个卡片容器宽度变化并动态切换布局类:
const card = document.querySelector('.card');
const observer = new ResizeObserver(entries => {
const { width } = entries[0].contentRect;
card.classList.toggle('layout-grid', width > 768);
card.classList.toggle('layout-stack', width <= 768);
});
observer.observe(card);
这段代码简洁、无副作用、响应精准,且在卡片被 JS 插入、CSS 动画展开、响应式断点切换等场景下均可靠工作。


















