VisualViewport

Baseline 广泛可用 *

此特性已发展成熟,可在多种设备和浏览器版本上使用。自 ⁨2021 年 8 月⁩ 起,它已在所有浏览器中可用。

* 此特性的某些部分可能存在不同级别的支持。

VisualViewport 接口是 Visual Viewport API 的一部分,用于表示给定窗口的可视视口。对于包含 iframe 的页面,每个 iframe 以及包含它的页面都会有一个唯一的窗口对象。页面上的每个窗口都有一个唯一的 VisualViewport,用于表示与该窗口关联的属性。

您可以通过 Window.visualViewport 获取窗口的可视视口。

注意: 只有顶层窗口的可视视口才与布局视口不同。因此,通常只有顶层窗口的 VisualViewport 对象才有用。对于 <iframe>,可视视口度量(例如 VisualViewport.width)始终对应于布局视口度量(例如 document.documentElement.clientWidth)。

EventTarget VisualViewport

实例属性

还继承了其父接口 EventTarget 的属性。

VisualViewport.offsetLeft 只读

返回可视视口的左边缘与布局视口左边缘的偏移量,以 CSS 像素为单位。

VisualViewport.offsetTop 只读

返回可视视口的顶部边缘与布局视口顶部边缘的偏移量,以 CSS 像素为单位。

VisualViewport.pageLeft 只读

返回可视视口相对于顶边初始包含块原点的 x 坐标,以 CSS 像素为单位。

VisualViewport.pageTop 只读

返回可视视口相对于顶边初始包含块原点的 y 坐标,以 CSS 像素为单位。

VisualViewport.width 只读

返回可视视口的宽度,以 CSS 像素为单位。

VisualViewport.height 只读

返回可视视口的高度,以 CSS 像素为单位。

VisualViewport.scale 只读

返回应用于可视视口的捏合缩放因子。

实例方法

还继承了其父接口 EventTarget 的方法。

事件

使用 addEventListener() 或将事件监听器分配给此接口的相应 oneventname 属性来监听这些事件。

resize

当可视视口大小调整时触发。也可通过 onresize 属性访问。

scroll

当可视视口滚动时触发。也可通过 onscroll 属性访问。

scrollend

当可视视口的滚动操作结束时触发。也可通过 onscrollend 属性访问。

示例

缩放时隐藏覆盖框

此示例摘自 Visual Viewport README,展示了如何编写少量代码,在用户放大页面时隐藏覆盖框(例如广告)。这是一个改善用户在放大页面时体验的好方法。还有一个 实时示例

js
const bottomBar = document.getElementById("bottom-bar");
const viewport = window.visualViewport;

function resizeHandler() {
  bottomBar.style.display = viewport.scale > 1.3 ? "none" : "block";
}

window.visualViewport.addEventListener("resize", resizeHandler);

模拟 position: device-fixed

此示例也摘自 Visual Viewport README,展示了如何使用此 API 来模拟 position: device-fixed,该属性将元素固定到可视视口。还有一个 实时示例

js
const bottomBar = document.getElementById("bottom-bar");
const viewport = window.visualViewport;
function viewportHandler() {
  const layoutViewport = document.getElementById("layoutViewport");

  // Since the bar is position: fixed we need to offset it by the visual
  // viewport's offset from the layout viewport origin.
  const offsetLeft = viewport.offsetLeft;
  const offsetTop =
    viewport.height -
    layoutViewport.getBoundingClientRect().height +
    viewport.offsetTop;

  // You could also do this by setting style.left and style.top if you
  // use width: 100% instead.
  bottomBar.style.transform = `translate(${offsetLeft}px, ${offsetTop}px) scale(${
    1 / viewport.scale
  })`;
}
window.visualViewport.addEventListener("scroll", viewportHandler);
window.visualViewport.addEventListener("resize", viewportHandler);

注意: 应谨慎使用此技术;以这种方式模拟 position: device-fixed 可能会导致固定元素在滚动时闪烁。

规范

规范
CSSOM 视图模块
# the-visualviewport-interface

浏览器兼容性

另见

  • Web Viewports Explainer — 对 Web 视口概念的有用解释,包括可视视口和布局视口之间的区别。