浏览器决定加载1x还是2x图片的关键在于img标签的srcset是否含合法1x/2x描述符且未设置sizes属性;若设置了sizes,dpr被忽略,转为宽度匹配模式;2x必须放在img的srcset中,source中的2x因条件匹配机制而无效。

浏览器怎么决定加载 1x 还是 2x 图片
关键不在 <picture></picture>,而在 srcset 里有没有合法的 1x/2x 描述符,且 sizes 不能存在——只要 <img> 上写了 sizes,哪怕值是 "100vw",2x 就直接失效,浏览器切到宽度匹配模式,DPR 被忽略。
常见现象:你明明写了 photo@2x.jpg 2x,Network 面板却只看到 @1x.jpg 加载。大概率是因为:
-
<img>标签上误加了sizes属性 -
<source></source>的srcset里写了2x,但该<source></source>又带了media(比如media="(max-width: 768px)")→ 此时浏览器只取第一个可用项,2x彻底不参与决策 -
srcset值里有非法空格,例如"a@2x.jpg 2x"(两个空格),整个属性被解析为无效,回退到src
为什么 里的 2x 总是不生效
<source></source> 的作用是“条件候选”,不是“DPR 切换器”。它只管匹配 media 或 type,一旦匹配成功,就直接用 srcset 里从左到右第一个 URL,后面跟着的 2x、3x 全部被跳过。
想让 DPR 生效,必须把 2x 放在最外层 <img> 的 srcset 里,并确保它没配 sizes:
- ✅ 正确结构:
<picture><source media="(max-width: 480px)" srcset="sm.jpg"><img src="lg.jpg" srcset="lg.jpg 1x, lg@2x.jpg 2x"></source></picture> - ❌ 错误结构:
<source media="(max-width: 480px)" srcset="sm.jpg 1x, sm@2x.jpg 2x"></source>→sm.jpg一定被加载,2x白写 - ⚠️ 注意顺序:
srcset="a@1x.jpg 1x, a@2x.jpg 2x"是安全的;但写成"a@2x.jpg 2x, a@1x.jpg 1x",在 DPR=1 设备上可能仍加载@2x(浏览器行为未完全标准化)
验证 2x 是否真被加载,别靠猜
不要看 window.devicePixelRatio,不要信控制台 log,唯一可靠方式是抓实际网络请求:
- 打开 Chrome DevTools → Network 面板 → 刷新页面
- 筛选类型为
Img,找到对应图片资源 - 右键 →
Copy image src→ 粘贴进新标签页,确认 URL 后缀是@2x.jpg还是@1x.jpg - 切到 DevTools → ⚙️ → Sensors → Device pixel ratio → 改成
1或2,然后硬刷新(Ctrl+Shift+R或Cmd+Shift+R),普通刷新可能走缓存
模拟器改 DPR 后没变化?八成是没硬刷新,或者服务端返回了 304 Not Modified。
高 DPR 下图片还是模糊,问题往往不在选图逻辑
即使 @2x.jpg 成功加载,显示仍糊,通常卡在 CSS 层:
-
img被设了固定width/height(如width: 300px; height: 200px),导致 600×400 的图被强行压缩进 300×200 容器,物理像素被丢弃 - 缺
max-width: 100%; height: auto,图片超出父容器后被裁剪或拉伸变形 - 用了
transform: scale(2)放大 —— 这是像素级放大,不是换源,必然模糊;正确做法是换更高分辨率图源
真正难的不是写对 srcset,而是让这张 @2x.jpg 在 DOM 里以原始像素密度渲染出来——这一步漏掉,前面全白搭。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











