根本原因是浏览器用低物理像素资源填充高物理像素区域,修复关键在于让渲染单元对齐设备像素比dpr:canvas需同步设置width/height×dpr并ctx.scale(dpr,dpr),img用srcset时只混用w描述符且sizes写死,background-image优先用媒体查询兜底,dpr须动态监听matchmedia而非仅初始化读取。

大屏设备(如 4K 显示器、MacBook Pro、Windows 高缩放显示器)上 HTML 内容模糊,根本不是“分辨率太高”,而是浏览器用低物理像素资源去填充高物理像素区域,触发插值拉伸——修复关键不在调 CSS,而在让每个渲染单元对齐设备像素比 window.devicePixelRatio。
canvas 渲染模糊:width/height 没乘 dpr 就等于白干
Canvas 在 4K 屏或 Windows 150% 缩放下发虚,90% 情况是只改了 canvas.style.width,却没同步放大 canvas.width 和 canvas.height。
-
canvas.style.width控制显示大小(CSS 像素),canvas.width才是绘图缓冲区的物理像素数 - 必须写:
canvas.width = rect.width * dpr、canvas.height = rect.height * dpr,其中rect = canvas.getBoundingClientRect() - 漏掉
ctx.scale(dpr, dpr),所有坐标会错位——比如你画ctx.fillRect(10, 10, 1, 20),在 DPR=2 下实际只占 0.5×10 物理像素,肉眼不可见 - 监听
matchMedia('(resolution)')而非仅resize:窗口拖到外接显示器时,resize不触发,但dpr已变
img 标签模糊:srcset 里混用 w 和 x 描述符会选错图
用 srcset 本意是让浏览器选高清图,但写错描述符反而让它加载更糊的版本。
- 只用
w描述符(如"img-800.jpg 800w"),别和2x混写——浏览器解析逻辑冲突,Chrome 可能直接 fallback 到src -
sizes必须写死 CSS 像素宽度,例如"(max-width: 768px) 100vw, 50vw",不能写"100%"或留空;差 10px 都可能让浏览器选错资源 -
src是 fallback,必须存在且为中等分辨率(如 800w),别设成 400w 小图——否则 DPR=1.25 时连 fallback 都糊 - 上线前用 Chrome DevTools → Network → Filter
image,看实际加载的是哪张,别信“写了就生效”
background-image 模糊:image-set() 在 Safari 旧版会静默失败
背景图不支持 srcset,靠 image-set() 或媒体查询适配,但兼容性陷阱多。
-
background-image: image-set(url(bg.jpg) 1x, url(bg@2x.jpg) 2x)在 Safari ≤15.6 中不生效,降级为 1x 图,用户全屏时立刻糊 - 稳妥做法是用媒体查询兜底:
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)单独覆盖高清规则 - 禁用
background-attachment: fixed:滚动时频繁重绘,部分浏览器主动降质渲染,尤其在 4K 外接屏上明显 - 真要全屏背景,优先换用
<img>+object-fit: cover+srcset,可控性远高于 CSS background
contenteditable 光标与文字发虚:浏览器亚像素渲染没法 JS 干预
富文本编辑器在高分屏下光标抖动、文字边缘毛,不是 JS 能 draw 出来的,得绕开默认渲染路径。
- 加 CSS 强制锐化:
image-rendering: -webkit-optimize-contrast(Safari)、image-rendering: crisp-edges(Chrome/Firefox),对光标框和图标有效 - 别用
transform: scale(0.5)模拟缩放——它把所有渲染误差也放大了;应改用font-size和line-height等比缩放 - 自定义 SVG 光标时,
stroke-width必须按dpr动态设置,例如逻辑粗 1px → 实际写stroke-width="1"+style="transform: scale(${dpr})" -
getBoundingClientRect()返回的是 CSS 像素,用于 canvas 绘制前必须手动 ×dpr,否则光标定位偏移
真正容易被忽略的点是:DPR 不是静态值,它会随窗口跨屏、系统缩放设置变更而实时变化;任何只在页面初始化时读一次 window.devicePixelRatio 的逻辑,都会在外接显示器或调整缩放后失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











