父页面 document.fullscreenelement 始终为 null,因为全屏状态严格属于子 iframe 的独立 browsing context,父页无法感知或接管;需通过 postmessage 由子页主动同步状态。

iframe 全屏时父页面 document.fullscreenElement 为什么是 null
因为全屏状态属于“当前激活文档”,而 iframe 是独立的 browsing context。子页面调用 document.documentElement.requestFullscreen() 后,全屏状态只存在于子 document 内部,父页面的 document.fullscreenElement 不会指向该 iframe 元素,也不会变成非 null —— 它始终为 null。
这不是 bug,而是浏览器严格按规范实现的权限隔离:父页无法“接管”子页的全屏状态,也不能通过 DOM 查询间接获取。想确认子页是否全屏,不能靠 parent.document.fullscreenElement === iframeElm 这类判断。
- 子页全屏后,父页
document.fullscreenElement永远是null,哪怕 iframe 元素本身在视口里占满整个屏幕 -
iframeElm.requestFullscreen()在绝大多数浏览器中直接报错或静默失败 —— 这个 API 只对<video></video>、<canvas></canvas>等可全屏媒体元素有效,不适用于<iframe></iframe> - 若需视觉上“让 iframe 占满”,只能由子页内部触发全屏,父页仅负责 UI 响应与状态同步
allow="fullscreen" 和 sandbox 属性必须同时配齐
仅加 allow="fullscreen" 不够,如果 iframe 同时启用了 sandbox,就必须显式包含该 token,否则全屏请求会被浏览器直接拦截,连错误都不会抛出。
常见误配:<iframe src="child.html" sandbox="allow-scripts" allow="fullscreen"></iframe> —— 这里 allow="fullscreen" 会被 sandbox 覆盖,实际无效。正确写法是把权限合并进 sandbox:
<iframe src="child.html" sandbox="allow-scripts allow-fullscreen"></iframe>
-
allowfullscreen是旧属性,allow="fullscreen"是新语法,但两者不能混用;现代项目建议统一用allow="fullscreen" - 如果已启用
sandbox,allow="fullscreen"必须写在 sandbox 值里,即sandbox="allow-scripts allow-fullscreen" - 跨域 iframe 下,即使加了权限,子页仍需自己调用
requestFullscreen();父页不能 proxy 调用,否则被拒绝
全屏状态必须靠 postMessage 显式同步
父子页之间没有自动状态同步机制。子页进入/退出全屏时,父页无法监听到自身 fullscreenchange 事件,必须依赖子页主动发消息。
子页代码示例:
document.addEventListener('fullscreenchange', () => {
const isFull = !!document.fullscreenElement;
window.parent.postMessage({ type: 'fullscreen-state', isFull }, '*');
});
父页监听示例:
window.addEventListener('message', e => {
if (e.data.type === 'fullscreen-state') {
// 更新按钮状态、隐藏/显示工具栏等
toggleFullscreenUI(e.data.isFull);
}
});
- 不要用
'*'在生产环境做postMessage的 targetOrigin,应校验e.origin是否可信 - 子页发消息时机必须在
fullscreenchange触发后,不能在requestFullscreen()调用后立刻发 —— 后者可能失败,且状态未真正变更 - 移动端 WebView 或旧版 Safari 可能 fallback 到缩放而非真全屏,此时
document.fullscreenElement仍为null,需结合window.innerHeight === screen.height等兜底判断
用户手势必须发生在 iframe 内部
这是最容易忽略的硬性限制:全屏必须由 iframe 内部的真实用户操作触发(如点击、空格键),不能由父页按钮点击后去调子页的 requestFullscreen()。
以下写法在 Chrome/Firefox 中必然失败:
// ❌ 父页中
document.getElementById('btn').onclick = () => {
iframe.contentWindow?.requestFullscreen(); // 被拒绝
};
- 正确路径是:子页内放一个按钮,绑定 click → 调
requestFullscreen()→ 监听fullscreenchange→ 发postMessage - 即使 iframe 同源,父页也无法绕过这个手势链;浏览器检查的是事件路径上的 active document,不是调用栈
- 某些安卓 WebView 对手势来源更敏感,连 iframe 内的
setTimeout延迟触发都会被判定为非用户驱动
postMessage 做轻量协同。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











