唯一可靠方案是postMessage双向通信:子页在window.load后取documentElement.scrollHeight并校验targetOrigin发送带type的消息;父页严格校验event.origin和source后再更新iframe.style.height。

跨域 iframe 无法直接读取 contentDocument,硬写 height 属性或靠 CSS 拉伸都不可靠——唯一能落地的方案是父子页用 postMessage 双向通信,且必须校验 event.origin。
子页面怎么发高度消息?
子页面(即 iframe 内的 HTML)不能等 DOM 渲染完就立刻发,得等所有资源(尤其是异步加载的内容、图片、JS 渲染结果)稳定后再测高。常见错误是只监听 DOMContentLoaded,但此时图片还没加载完,scrollHeight 偏小。
- 推荐在
window.addEventListener('load', ...)中触发测量,确保所有资源加载完毕 - 高度取值优先用
document.documentElement.scrollHeight,它比document.body.scrollHeight更可靠(尤其在某些 CSS 重置后body高度可能为 0) - 发送时别用
'*'当 targetOrigin,必须写死父页域名,比如'https://your-main-site.com' - 加个 type 字段便于父页过滤,例如
{ type: 'iframeResize', height: 842 }
父页面怎么安全接收并更新 iframe?
收到消息不等于能直接信——任意网站都能往你的页面发 message,不校验来源就是开放攻击面。
- 必须检查
event.origin是否匹配预期域名,不能只看event.data.type - 建议额外校验
event.source === iframe.contentWindow,防止被其他同页 iframe 干扰 - 更新高度时,优先改
iframe.style.height而非iframe.height属性,避免被内联样式覆盖 - 如果 iframe 宽度也要适配,同理传
width,但多数场景只需调高
为什么 resize 事件监听容易失效?
子页面里监听 window.resize 不代表内容高度真变了——比如一个折叠面板展开,页面没 resize,但内容高突增 200px。单纯靠 resize 会漏掉这类变化。
立即学习“前端免费学习笔记(深入)”;
- 真正要监听的是内容变化本身:DOM 插入、CSS 类切换、AJAX 回填后手动触发尺寸上报
- 若子页用 React/Vue,应在组件挂载完成、数据渲染完毕后调用一次
sendSize() - 可封装一个防抖函数,比如 100ms 内多次变化只发最后一次,避免频繁重绘
同域下能不能跳过 postMessage?
能,但不推荐。虽然同域时父页可直接读 iframe.contentDocument.documentElement.scrollHeight,但一旦未来子页迁到 CDN 或子域,就会突然报 SecurityError,而代码里没有任何 fallback。
- 统一走
postMessage路线,开发和上线逻辑一致,维护成本更低 - 同域子页发消息时,
targetOrigin仍建议写具体协议+域名,而非'*' - 父页的 message 监听器无需区分同域/跨域,一套逻辑跑通更稳妥
最易被忽略的点:子页发消息时没等渲染完成,父页收消息时没校验 event.origin——这两个漏洞会让自适应要么不生效,要么被恶意站点利用控制布局。


















