响应式图片在Retina屏模糊的根源是浏览器未加载匹配DPR的高分图,而是拉伸低分辨率图;必须用x描述符(如srcset="icon-100.png 1x, icon-200.png 2x")、image-set()配合显式background-size、媒体查询兜底,并确保图片物理尺寸真实翻倍。

响应式图片在 Retina 屏上模糊,不是因为 CSS 写错了,而是浏览器在高 DPR(如 2x/3x)下强行拉伸了低分辨率图——它压根没换图,只是把一张 1x 图“撑大”到两倍物理像素上渲染。
srcset + x 描述符没写对,浏览器根本不会加载 @2x 图
只写 srcset="icon-100.png 100w, icon-200.png 200w" 是无效的:w 描述符响应视口宽度,不响应设备像素比。iPhone 的 DPR=3,但视口 CSS 宽度可能只有 390px,浏览器就永远选第一张。
- 必须用
x描述符直连 DPR:srcset="icon-100.png 1x, icon-200.png 2x, icon-300.png 3x" -
src是兜底项,IE 全系只认它,不能省 - 构建工具(Vite/Webpack)通常不解析
srcset中的路径,要手动验证icon-200.png确实输出到了dist目录且可访问 - 安卓 WebView 对
x支持不稳定,必须搭配sizes才能触发高 DPR 加载
background-image 模糊,image-set() 不是粘贴即用
image-set() 只对 background-image 生效,且 Safari 6.1+/Chrome 21+/Edge 12+ 支持,Firefox 不解析内容(只走 fallback),IE 完全不认。
- 顺序不能反:
background-image: url("icon.png"); background-image: image-set("icon.png" 1x, "icon@2x.png" 2x);—— 后者覆盖前者 - 必须显式写
background-size: 24px 24px(按设计稿逻辑尺寸),否则@2x图会以 48×48 像素渲染成双倍大小 -
image-set()不支持w描述符,混写(如"icon.png" 800w)会导致整个函数静默失效 - 伪元素(
::before)里用时,必须有content: ""+display: block+ 显式宽高,否则背景无渲染区域
写了 image-rendering 却还是糊,因为它不解决资源选择问题
image-rendering: crisp-edges 只控制已有图片的渲染算法,不改变加载哪张图。如果 src 或 background-image 指向的仍是 @1x 图,再设这个属性也只是把模糊图“锐化显示”,不是变高清。
立即学习“前端免费学习笔记(深入)”;
- 仅对已缩放的位图生效;对
background-image完全无效(CSS 背景图无视该属性) - 像素风图标可用
-webkit-optimize-contrast+crisp-edges;照片类请保持auto,否则色阶断裂 - Tailwind 或重置 CSS 可能悄悄注入
image-rendering: smooth,覆盖你的设置 - 真正起作用的前提是:浏览器已加载了匹配 DPR 的高分图
媒体查询兜底不是可选项,是必须项
image-set() 和现代 srcset 在旧 Safari、部分安卓 WebView、Firefox(无前缀)中会完全失效,此时只能靠媒体查询硬切。
- 用
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx),比192dpi更可靠(避免单位换算误差) - 基础规则写在前面(1x 图 +
background-size),媒体查询覆盖在后,否则 1x 始终生效 - 媒体查询内必须重复写
background-size,否则高清图加载后仍按默认方式缩放 - 不要依赖
background-size: cover自动适配——不同 DPR 下缩放比例不一致,关键区域容易被裁错
最易被忽略的点:所有方案都依赖「图的物理尺寸必须真实翻倍」。用 PS 把 1x 图放大保存为 @2x,或让构建工具自动 resize,结果仍是插值拉伸——浏览器拿到的是一张“假高清图”,再怎么写 CSS 都救不回来。


















