核心问题是viewport缺失、width/height硬编码、dpr未适配三者并发;须在父页加viewport meta,用css比例盒或postmessage动态设高,并在子页按dpr缩放canvas。

核心问题不是 iframe 本身“错乱”,而是它在不同手机上渲染时,viewport缺失、width/height硬编码、DPR 未适配这三件事同时发生。单独修一个,大概率白忙。
父页没设 viewport 导致 iframe 容器尺寸失真
绝大多数“iframe 错位”根本不是 iframe 的锅——是父页面没加 <meta name="viewport">,浏览器用 980px 渲染后缩放,iframe 的 100% 就按这个假宽度算,结果在 iPhone 上只占半屏,或右侧留白。
- 必须在父页
中写:<meta name="viewport" content="width=device-width, initial-scale=1.0"> - 别写成多行或带多余空格,比如
content=" width=device-width ",旧版 WebView 会直接忽略整条 - 如果 iframe 源页你无法改(如第三方后台),就在父页给
<iframe></iframe>包一层<div class="iframe-container">,并用 CSS 强制约束比例<h3>iframe 高度写死或百分比失效导致内容截断/滚动条</h3> <p>移动端 WebView 对 <code>height: 100%支持极差,height="500"在小屏上撑爆,在大屏上又留白;直接设height: 100vh更糟——键盘弹出时vh值跳变,iframe 突然被压扁。- 推荐用 CSS 比例盒:
.iframe-container { position: relative; width: 100%; height: 0; padding-bottom: 56.25%; }+iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - 动态高度必须走
postMessage:子页 onload 后发window.parent.postMessage({ type: 'iframeHeight', height: document.documentElement.scrollHeight }, 'https://yourdomain.com'),父页严格校验event.origin后再设iframe.style.height - 别信
body.scrollHeight—— 移动端字体加载慢,优先读documentElement.scrollHeight,fallback 到body.scrollHeight
iframe 内部 Canvas / 字体在高 DPI 屏模糊
iPhone、华为 Mate 系列、三星 Fold 这些设备的
window.devicePixelRatio是 2 或 3,但 iframe 里的 canvas 如果还按 CSS 像素画图,就会被浏览器拉伸模糊——这不是抗锯齿开关能解决的,是像素密度没对齐。- 必须在 iframe 子页 JS 里做三件事:
canvas.width = Math.round(parentElement.getBoundingClientRect().width * window.devicePixelRatio),ctx.scale(dpr, dpr),canvas.style.width = parentElement.getBoundingClientRect().width + 'px' - 禁止对
<iframe></iframe>元素本身加transform: scale()或zoom,这是把整个渲染结果当位图拉伸,Canvas、SVG、字体全糊 - 跨域 iframe 无法注入脚本,DPR 适配完全失控——要么换同域,要么让对方提供带
?dpr=2参数的资源入口
最易被忽略的是:双屏设备(如 Fold)展开瞬间,
window.innerWidth还没更新,但visualViewport.width已就绪;只监听resize会错过第一帧布局,必须同时监听visualViewport变化。这不是兼容性补丁,是真实折叠动画里的关键帧。 - 推荐用 CSS 比例盒:











