iframe的width="100%"生效而height="100%"失效,是因为width百分比基于父容器宽度(通常自然撑开),而height百分比依赖父容器明确高度;若html、body及中间父容器未显式设height: 100%或100vh,height="100%"将退化为默认150px。

iframe width="100%" 为什么只生效、height="100%" 却总失效
因为 height 百分比依赖父容器有明确 height 值,而 width 百分比只依赖父容器宽度(通常由视口或块级容器自然撑开)。html、body、所有中间父容器若没显式设 height: 100% 或 height: 100vh,height="100%" 就会退化为默认 150px。
常见翻车点:
- 写了
<iframe width="100%" height="100%">,但父<div>没设height,结果 iframe 只剩一条细缝 - 用
display: flex包裹 iframe,却忘了给父容器加height: 100%—— flex 容器不设高度时,子项的height: 100%依然无效 - 移动端 Safari 在地址栏收起/展开时 viewport 高度变化,
100vh会错位,此时100%更不稳定
同源 iframe 动态读取 scrollHeight 的安全写法
同源(协议、域名、端口全一致)才能直接访问 contentDocument。但 onload 触发时 DOM 渲染未必完成,直接读 scrollHeight 极易偏小。
最小可靠操作:
立即学习“前端免费学习笔记(深入)”;
- 监听
iframe.onload,内部加setTimeout(() => { ... }, 0)确保重排完成 - 优先读
doc.documentElement.scrollHeight,fallback 到doc.body.scrollHeight,避免 DTD 声明差异导致为 0 - 用
Math.max(height, 300)设兜底最小高度,防内容为空时 iframe 塌陷 - 子页
<body>必须重置:body { margin: 0; padding: 0; },否则默认 8px 边距会被计入高度 - 设置时用
ifr.style.height = 'xxxpx',而非ifr.height = 'xxx',避免内联属性干扰 CSS
跨域 iframe 必须用 postMessage,且 origin 校验不能省
跨域时 contentDocument 被浏览器完全封锁,scrollHeight 读不到,onload 也拿不到尺寸——这不是兼容性问题,是安全策略强制要求。
父子通信必须满足:
- 子页在
window.addEventListener('load', () => { ... })中计算高度,再调用window.parent.postMessage({ type: 'resize', height }, 'https://trusted.com') - 父页监听
message事件,**必须校验e.origin === 'https://trusted.com'且e.source === ifr.contentWindow**,否则存在 XSS 风险 - 子页若用 Vue/React,需确保在
mounted或useEffect(() => {}, [])中发消息,避开 SSR 渲染阶段 - 父页收到消息后,仍要
Math.max(height, 300)再设高,防子页上报 0
width 属性单位和 style 写法的混用陷阱
width 和 height 是 iframe 原生属性,语义和行为与 CSS 不同:它们不支持 vw、vh、rem 等单位,只认像素数值或带 % 的字符串。
典型误用:
-
width="100"→ 解析为 100px,不是 100%,缺%符号 -
width="50vw"→ 完全无效,浏览器忽略该属性 - 想用
vw?必须改用style="width: 50vw;" - 父容器用了
display: flex,iframe 默认 inline 元素,底部会多出几像素空白,加style="display: block;"消除 - 设了
width="100%"但没处理高度,内容可能被横向拉伸或纵向截断——响应式 iframe 必须宽高协同
真正难的不是“怎么设”,而是判断当前是否同源、子页渲染节奏是否可控、以及 origin 校验漏掉一个字符就等于开放 XSS 入口。这些细节在开发时容易跳过,上线后才暴露。



















