iframe全屏必须同时设置allow="fullscreen"和allowfullscreen属性,且全屏调用须在子页内由用户手势触发,并通过postMessage同步状态。

iframe 全屏必须加 allow="fullscreen" 属性
不加这个,Chrome 120+、Firefox 新版、Safari 都会静默拒绝全屏请求——点按钮没反应,控制台可能只报 NotAllowedError,甚至完全无提示。旧写法 allowfullscreen(布尔属性)仅作兼容,跨域 iframe 下根本无效。
常见错误写法包括:allowfullscreen="true"(值多余)、allow="full-screen"(拼写错)、allow="allow-fullscreen"(非标准字符串)。唯一正确且推荐的写法是:
<iframe src="child.html" allow="fullscreen" allowfullscreen></iframe>
双写兼顾语义明确性与老浏览器兼容性,且不冲突。
- 若父页响应头含
Permissions-Policy: fullscreen 'none',HTML 属性会被直接覆盖,需同步调整响应头 - 子页加载后可在控制台执行
document.fullscreenEnabled,返回true才算权限就绪
全屏触发必须在 iframe 内部由用户手势调用
父页面不能代理调用子 iframe 的 requestFullscreen()。哪怕你拿到 iframe.contentWindow,只要不是同源,contentDocument 就是 null;即使同源,在 iframe.onload 或 setTimeout 里调用也会被浏览器拒绝——因为“用户手势”上下文不会跨 browsing context 传递。
立即学习“前端免费学习笔记(深入)”;
正确做法:子页 HTML 里放一个按钮,绑定原生 click 事件,直接调用自身 document 元素的 requestFullscreen():
<button onclick="document.documentElement.requestFullscreen()">进入全屏</button>
- 不要用
document.body或document.documentElement以外的目标(如空 div),Safari 对非语义容器支持不稳定 - 避免在
fetch().then、视频play()回调、DOMContentLoaded后调用,这些都不是用户手势同步上下文 - iOS Safari 建议统一用
click,不用touchend(部分机型有延迟或失效)
父页无法通过 document.fullscreenElement 感知 iframe 全屏状态
document.fullscreenElement 在父页永远为 null,这不是 bug,是规范行为:iframe 是独立文档,它的全屏状态不提升到父文档层级。别试图靠轮询或监听父页的 fullscreenchange 来判断子页是否全屏。
必须靠跨文档通信实现状态同步:
- 子页进入全屏后,立即发
postMessage({ type: 'fullscreen-enter' })给window.parent - 子页退出全屏时(监听自身
fullscreenchange),发postMessage({ type: 'fullscreen-exit' }) - 父页监听
message事件,根据event.data.type更新按钮文案、禁用滚动等 UI 行为
Safari 对 fullscreenchange 有微小延迟,子页发消息前可加 Promise.resolve().then(() => {...}) 确保 document.fullscreenElement 已更新。
document.exitFullscreen() 在 iframe 内必须显式调用
用户按 Esc 键退出后,子页 JS 不会自动响应,UI 状态极易脱节。比如按钮还显示“退出全屏”,实际已退出。所以子页必须自己监听 fullscreenchange,并在检测到 document.fullscreenElement === null 时,主动更新 UI;同时提供退出按钮,调用 document.exitFullscreen() 并捕获错误:
document.exitFullscreen().catch(e => {<br> if (e.name === 'NotAllowedError') console.warn('退出被拒,可能因非手势上下文');<br>});
-
document.exitFullscreen()也受手势限制,但放在fullscreenchange回调里调用通常是安全的 - 不要在
fullscreenchange里反复调用exitFullscreen(),否则可能引发循环或竞态(例如双击按钮) - 移动端(尤其 iOS)不支持真正全屏退出 API,此时需配合 CSS(如
body { height: 100vh; overflow: hidden; })模拟视觉还原



















