fullscreenchange 事件只能监听 document 对象,用于检测全局全屏状态变化;需通过 document.fullscreenelement 判断当前全屏元素,null 表示退出全屏,并注意 iframe 和 shadow dom 中该属性不包含其内部全屏元素。

fullscreenchange 事件监听的是 document 对象,不是元素
很多人一开始会尝试给某个 <video></video> 或 <div> 绑定 <code>fullscreenchange,结果发现完全不触发。这是因为该事件只在 document 上触发,它是全局全屏状态变化的唯一通知渠道。
正确做法是:
- 监听
document的fullscreenchange事件(注意拼写,不是fullscreenchanged) - 通过
document.fullscreenElement判断当前是否有元素处于全屏——它返回进入全屏的 DOM 元素,为null表示已退出全屏 - 不要依赖事件参数里的
target,它始终是document,无法反映哪个元素触发了全屏
判断全屏状态不能只看 event.type
fullscreenchange 事件本身不带“进入”或“退出”的语义字段,同一个事件名既用于进入也用于退出。错误写法如 if (e.type === 'fullscreenchange') 无法区分方向。
必须主动检查状态:
-
if (document.fullscreenElement)→ 正在全屏(任意元素) -
if (!document.fullscreenElement)→ 已退出全屏 - 若需精确知道是哪个元素进/出,可配合
fullscreenchange前后缓存document.fullscreenElement值做比对
示例片段:
let prevElement = null;
document.addEventListener('fullscreenchange', () => {
const curr = document.fullscreenElement;
if (curr && !prevElement) {
console.log('进入全屏,目标:', curr);
} else if (!curr && prevElement) {
console.log('退出全屏,原目标:', prevElement);
}
prevElement = curr;
});
注意浏览器前缀和兼容性差异
旧版 Chrome/Safari/Edge 曾使用带前缀的属性和事件,现在虽基本统一,但仍有边缘情况:
-
document.fullscreenElement是标准名;旧版对应document.webkitFullscreenElement、document.msFullscreenElement -
fullscreenchange是标准事件名;旧版对应webkitfullscreenchange、msfullscreenchange - 现代项目建议用
document.fullscreenElement !== undefined检测是否支持,再决定是否添加监听 - 移动端 Safari(iOS)完全不支持 API 触发全屏(仅允许视频原生控件全屏),但
fullscreenchange在桌面 Safari 中可用
常见误触发场景:iframe 和 shadow DOM
如果页面含 <iframe></iframe>,且子帧调用了 requestFullscreen(),父文档的 fullscreenchange 仍会触发,但 document.fullscreenElement 为 null(因为全屏的是 iframe 内部元素,不属于父文档树)。
类似地,在 Shadow DOM 中调用 element.requestFullscreen() 后,宿主文档的 fullscreenElement 也不会包含该元素——它只返回 light DOM 中的匹配节点。
这意味着:
- 无法通过父文档监听准确获知 iframe 或 shadow root 内部的全屏状态
- 若需跨上下文同步状态,需手动通过
postMessage或自定义事件透传 - 调试时看到事件触发但
fullscreenElement为空,先检查是否涉及嵌套上下文











