根本原因是iframe内页面的canvas、img或css未适配devicepixelratio;需在iframe内部独立完成dpr适配:重设canvas宽高、调用ctx.scale()、设置style.width,并通过postmessage同步dpr值,禁用transform缩放。

iframe 内容在高 DPI 屏上模糊,根本原因不是 iframe 本身
模糊来自 iframe 内部页面的 Canvas、<img> 或 CSS 渲染未适配 window.devicePixelRatio。iframe 只是容器,它不缩放内容,也不自动补偿 DPR —— 父页和子页的 DPR 处理必须各自独立、且保持一致。常见错误是只在父页做 rem 适配,而 iframe 里仍用固定 px 值画图或设字体,结果在 Retina 屏上被浏览器拉伸模糊。
Canvas 在 iframe 里绘制模糊,必须重设 width/height + ctx.scale()
iframe 中的 <canvas></canvas> 不能依赖父页逻辑;必须在 iframe 内部 JS 中执行完整高 DPI 适配:
- 用
canvas.parentElement.getBoundingClientRect()获取视觉尺寸(不是offsetWidth,后者不响应缩放) - 设置
canvas.width = Math.round(visualWidth * window.devicePixelRatio)和同理的height - 调用
ctx.scale(devicePixelRatio, devicePixelRatio),否则所有坐标会偏移 - CSS 上必须显式设
canvas.style.width = visualWidth + 'px',否则浏览器按物理像素撑开布局
漏掉任意一步,比如只改 width 不调 ctx.scale(),绘图就会挤成一团或严重偏移。
iframe 自身缩放导致子页文字/按钮变糊,禁用 CSS transform 缩放
用 transform: scale() 缩放整个 iframe 元素是危险操作:它把子页所有像素当位图拉伸,Canvas、SVG、甚至字体都会模糊。正确做法是让 iframe 源页自己适配 DPR,然后仅通过 CSS 控制 iframe 的 width/height(用 rem 或 viewport 百分比),而不是用 transform 或 zoom。
若必须动态缩放(如大屏投屏),优先用 JS 修改 iframe 的 src 查询参数(例如 ?scale=2),让子页主动加载对应 DPR 的资源并重设根字体。
父页与 iframe 的 DPR 不同步,会导致定位偏移和字体渲染不一致
即使 iframe 页面做了 DPR 适配,如果父页用了 rem 动态根字号但没同步传值,iframe 内部 getBoundingClientRect() 返回的坐标可能和父页视觉位置对不上。尤其当父页监听了 resize 但 iframe 没监听 message 或 postMessage 通信时,横竖屏切换后偏移更明显。
建议方案:
- 父页通过
window.postMessage({ type: 'dpi-sync', dpr: window.devicePixelRatio })主动通知 iframe - iframe 内监听
message,收到后立即执行document.documentElement.style.fontSize重算 - 避免在 iframe 内直接读取
window.devicePixelRatio后不做校验——某些安卓 WebView 会返回1即使实际 DPR 是 2.5
最易忽略的是:iframe 加载完成前就调用 getBoundingClientRect(),此时返回的尺寸为 0 或默认值,后续 DPR 适配再生效也来不及修正定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











