Resize Observer API
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2020.
Resize Observer API 提供了一种高性能的机制,通过该机制,代码可以监视元素的大小更改,并且每次大小更改时都会向观察者传递通知。
概念和使用
存在大量的响应式设计(以及其他相关)技术,它们可以响应元素大小的变化,但是以前,它们的实现常常很笨拙或者说生硬。
举个例子,当视口更改大小时,媒体查询 / window.matchMedia
非常适合在特定点更新布局,但是如果要响应于特定元素的大小更改而更改布局,该元素又不是外部容器时,该怎么办?
为此,一种有限的解决方案是监听对适当事件的更改,该事件会提示你对更改大小感兴趣的元素(例如 window resize 事件),然后找出该元素之后新的尺寸或其他功能,例如,使用Element.getBoundingClientRect
或者Window.getComputedStyle
,来调整大小。
这样的解决方案仅适用于有限的场景,对性能不利(不断调用上述方法会导致性能严重下降),并且在不更改浏览器窗口大小的情况下通常不起作用。
Resize Observer API 提供了一种解决此类问题的解决方案,此外,它还使你能够轻松观察和响应元素内容或边框的大小变化,并以高效的方式做出响应。它为 Web 平台中经常讨论的,缺乏元素查询提供了 JavaScript 解决方案。
用法很简单,并且与其他观察者(例如 Performance Observer 或者 Intersection Observer)几乎相同——你可以使用 ResizeObserver()
构造函数创建一个新的 ResizeObserver
,然后使用 ResizeObserver.observe()
使其寻找特定元素大小的更改。每次更改大小时,构造函数中设置的回调函数便会运行,从而提供对新尺寸的访问,并允许你根据需要执行任何操作。
接口
ResizeObserver
-
提供注册新观察者以及启动和停止观察元素的能力。
ResizeObserverEntry
-
描述已调整大小的单个元素,标识该元素及其新大小。
示例
你可以在我们的 GitHub 存储库中找到几个简单的示例:
- resize-observer-border-radius.html(源码):一个带有绿色框的简单示例,其大小为视口大小的百分比。更改视口大小时,框的圆角将根据框的大小成比例地变化。我们可以通过
border-radius
的百分比来实现,但这很快就会导致丑陋的椭圆形角,而上述解决方案为你提供了随盒子大小缩放的漂亮的圆角。 - resize-observer-text.html (源码): 这里我们使用 resize observer 来改变
font-size
,标题和段落的值随着滑块值的改变而改变,导致包含的<div>改变宽度。这表明你可以响应元素大小的变化,即使它们与视口无关。
代码通常将遵循这种模式(取自 resize-observer-border-radius.html):
const resizeObserver = new ResizeObserver((entries) => {
const calcBorderRadius = (size1, size2) =>
`${Math.min(100, size1 / 10 + size2 / 10)}px`;
for (const entry of entries) {
if (entry.borderBoxSize) {
entry.target.style.borderRadius = calcBorderRadius(
entry.borderBoxSize[0].inlineSize,
entry.borderBoxSize[0].blockSize,
);
} else {
entry.target.style.borderRadius = calcBorderRadius(
entry.contentRect.width,
entry.contentRect.height,
);
}
}
});
resizeObserver.observe(document.querySelector("div"));
规范
Specification |
---|
Resize Observer # resize-observer-interface |
浏览器兼容性
BCD tables only load in the browser