视网膜屏图片模糊的根源是浏览器未获取匹配dpr的源图,主因包括srcset误用、picture配置缺失media/type/srcset、img缺少src,以及服务器mime类型不匹配等。

视网膜屏上图片模糊,不是图不够大,而是浏览器没拿到匹配 DPR 的源图——srcset 用错、<picture></picture> 配置漏项、或 <img src> 缺失,都会导致高分屏强行拉伸 1x 图。
为什么写了 <picture></picture> 却始终加载同一张图
浏览器不会主动适配视网膜屏,它只按 <source></source> 的 media、type、srcset 严格匹配。一个都不中,就直接 fallback 到 <img src>。
-
media值写错:比如media="max-width: 768px"缺括号,或写成media="768px"(非媒体查询语句),浏览器直接忽略该<source></source> -
<source></source>有srcset但没配media或type:该<source></source>不参与选择,等于白写 -
<img>缺src:页面留空,不是报错,是静默失败;老浏览器(如 IE)也完全不看srcset,只依赖src - Network 面板看到
blocked:mime-type:说明服务器返回的Content-Type和你写的type="image/webp"不一致(比如返回text/plain)
srcset 中 1x/2x 必须显式声明,w 描述符不管用
适配视网膜屏(DPR=2/3)只认 1x、2x、3x 这种写法;w 描述符需配合 sizes 按布局宽度算——那是另一套逻辑,和 DPR 无关。
- 正确写法:
srcset="photo.jpg 1x, photo@2x.jpg 2x, photo@3x.jpg 3x" - 最高倍率图必须放最后:浏览器从左到右匹配,遇到第一个满足 DPR 的就停;如果
3x放前面,2x设备永远选不到2x图 - 禁止混用:
photo-400w.jpg 400w, photo@2x.jpg 2x是未定义行为,Chrome 可能整个srcset忽略 -
<img src>不是可选项,而是强制兜底:它应指向中等清晰度、体积适中的版本(比如 800w JPEG),既防小屏浪费带宽,也不致桌面端糊成一片
<picture></picture> 不是万能,但三条件同时存在时它不可替代
只有当你要同时满足「不同屏幕宽度 + 不同设备像素比 + 不同图片格式或裁剪方式」时,<picture></picture> 才是唯一解法。
- 例如:手机端需要竖构图小图、桌面端需要横构图大图、且桌面端优先用
webp - 每个
<source></source>可独立指定media(宽度)、type(格式)、srcset(含w或x) -
<img>是 fallback,必须存在;它的src不参与匹配逻辑,只在所有<source></source>都不命中时才加载 -
type="image/webp"在 Safari 14+ 才被完全支持;旧版 Safari 会跳过该<source></source>,直接走<img>fallback
调试时别信“我写了 2x 就一定加载 2x 图”
打开 DevTools → Network → 刷新,点开图片请求,检查 Request Headers 里的 dpr 和实际加载的 URL。很多模糊问题根本不是代码写错,而是构建工具没生成 @2x 文件、CDN 缓存了旧资源、或静态路径配置漏了后缀映射。
- Webpack/Vite 构建时,静态资源路径不会自动补
@2x后缀;icon@2x.png404 是常见问题,得靠插件(如vite-plugin-imagemin)或手动配置 resolve 规则 - 即使你只打算支持现代浏览器,也别省略
<img src>——缓存失效、CDN 配置错误、MIME 类型错位时,它就是最后一道防线 - 真正容易被忽略的是:所有
<source></source>匹配失败后,浏览器不会报错,也不会警告,只会安静地加载<img src>;你得自己去 Network 面板确认它到底加载了哪张
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











