页面切到后台,标签里的视频还在放——不是你写漏了,是浏览器终于把这个功能原生化了
页面切到后台,标签里的视频还在放——不是你写漏了,是浏览器终于把这个功能原生化了。
这个场景困扰了前端开发者很多年:页面上嵌入了一个第三方视频 iframe(比如 YouTube 嵌入),用户切换到别的标签页,后台那个视频还在出声。传统的解法是在外层页面监听 document.visibilitychange,当页面隐藏时手动找到那个 iframe 里的 video 元素调 pause(),回来时再调 play()。这套逻辑每个用 iframe 嵌视频的页面都要写一遍,而且稍微封装不好就会漏掉某些边缘情况。
Chrome 155 把这件事用一行属性彻底原生化了。
<iframe src="https://example.com/video"
allow="media-playback-while-not-visible">
</iframe>
加上 allow="media-playback-while-not-visible" 这行之后,浏览器自动接管隐藏 iframe 里的媒体播放状态:当 iframe 的 display 被设为 none、visibility 被设为 hidden,或者宽高为零(零面积)时,浏览器会主动阻止该 iframe 内的任何音频或视频播放。当 iframe 重新恢复可见时,浏览器自动解除禁止,媒体继续正常播放。整个过程页面端不需要写一行 JavaScript。
这个机制基于 WHATWG iframe-media-pausing 规范,由 Microsoft 贡献代码。支持的媒体类型目前包括 HTMLMediaElement(video 和 audio 元素)以及 Web Audio 的 AudioContext。Chrome 155 desktop 和 Android 同步上线。Mozilla 也在实现支持。
值得注意的是,这套机制需要 iframe 主动声明才生效(<iframe allow="media-playback-while-not-visible">),如果没写这行,浏览器的默认行为不变。这样设计的目的是防止嵌入的第三方 iframe 偷偷借助浏览器能力实现不期望的行为,安全策略默认是收紧的。
配合这套机制,还有两个渐进增强的使用建议:
第一,保留 visibilitychange 降级逻辑。 如果你的页面要同时支持没有此特性的旧版浏览器,建议在 JS 里保留 visibilitychange 监听器作为降级方案——当浏览器不支持 media-playback-while-not-visible 时,手动暂停逻辑仍然生效。
// 降级:旧浏览器下仍然手动处理
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
iframe.contentWindow?.postMessage({ type: 'pause' }, '*');
}
});
第二,iframe 内嵌通信不要依赖 DOM 事件。 如果你依赖 iframe 内嵌的 postMessage 通信来同步播放状态,要注意浏览器自动暂停/恢复的时机和你的 JS 逻辑之间不会产生冲突——因为这些操作不触发任何 DOM 事件,只是内部状态变更。
Chrome 155 这一批同步上线的还有一项相关改进:隐藏 iframe 的内容会从无障碍树中移除,这意味着屏幕阅读器也不会朗读后台标签里 iframe 中的内容。这两个改动共同让 iframe 在页面可见性变化时的行为更加可预期。
下一步:如果你在页面上嵌入了视频或音频 iframe,先检查一下这些 iframe 是否有 allow="media-playback-while-not-visible";如果没有,加上这行属性,然后在页面的 visibilitychange 监听器里移除手动暂停/恢复的逻辑——浏览器会替你兜底。
参考资料
- Chrome Platform Status: https://chromestatus.com/feature/5082950457884672
- Intent to Ship: https://groups.google.com/a/chromium.org/g/blink-dev/c/cRwXwL3b1fM/
- WHATWG iframe-media-pausing: https://wicg.github.io/iframe-media-pausing
- Microsoft Edge Explainer: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/IframeMediaPause/iframe_media_pausing.md
评论区
登录后可评论。