Resize Observer API

Baseline 已广泛支持

此特性已经十分成熟,可在许多设备和浏览器版本上使用。自 2020 年 7 月以来,它已在各大浏览器中可用。

Resize Observer API 提供了一种高效的机制,代码可以通过它来监视元素的尺寸变化,并在每次尺寸改变时向观察者发送通知。

概念与用法

有很多用例可以通过响应元素尺寸变化的响应式设计技术(以及其他方面)来实现,但以前的实现往往是 hacky 和/或脆弱的。

例如,媒体查询 / window.matchMedia 非常适合在视口尺寸变化时在特定点更新布局,但如果你想根据特定元素的尺寸变化来改变布局,而不是外部容器呢?

要实现这一点,一个有限的解决方案是监听可能暗示你感兴趣的元素尺寸变化的事件(例如,窗口的 resize 事件),然后使用 Element.getBoundingClientRectWindow.getComputedStyle 等方法来确定元素在 resize 后的新尺寸或其他特征。

这样的解决方案往往只适用于有限的用例,对性能不利(持续调用上述方法会导致性能急剧下降),并且当浏览器窗口大小未改变时通常无效。

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)

js
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"));

规范

规范
Resize Observer(调整大小观察器)
# resize-observer-interface

浏览器兼容性

另见