浏览器只在最外层<img>的srcset中解析1x/2x,<source>里的2x被完全忽略;若<img>设了sizes,则DPR匹配失效,转为宽度匹配模式;验证必须通过Network面板抓包确认实际加载URL。

picture 里 的 2x 描述符根本不起作用
浏览器只在最外层 <img> 的 srcset 中解析 1x/2x,<source> 即使写了 icon@2x.png 2x 也会被完全忽略。这不是 bug,是规范行为:只要 <source> 带了 media 或 type,它的 srcset 就只按顺序取第一个资源,DPR 匹配逻辑不介入。
常见错误写法:<picture><source media="(max-width: 480px)" srcset="btn-small@2x.png 2x"><img src="btn-small@1x.png"></picture>
结果:小屏设备永远加载 btn-small@2x.png,哪怕 DPR=1。
- 正确做法是把所有 DPI 版本都挪到
<img>的srcset里,例如:srcset="btn@1x.png 1x, btn@2x.png 2x, btn@3x.png 3x" -
<source>只负责宽度断点或格式降级,比如用type="image/webp"或media="(min-width: 768px)" - 如果只用 DPI 切换、不涉及宽度变化,
<picture>其实可省,直接<img srcset="...">更简洁
img 的 srcset + sizes 会禁用 2x 匹配
一旦你在 <img> 上写了 sizes 属性(哪怕只是 sizes="100vw"),浏览器就切换到「宽度匹配模式」,彻底忽略 1x/2x 描述符——它会根据 sizes 计算出图片渲染宽度,再从 srcset 中选最接近的 w 候选项。
按钮图标这类固定尺寸元素,通常不需要 sizes。强行加反而破坏 DPI 适配。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确:
<img src="btn@1x.png" srcset="btn@1x.png 1x, btn@2x.png 2x, btn@3x.png 3x"> - ❌ 错误:
<img src="btn@1x.png" srcset="btn@1x.png 1x, btn@2x.png 2x" sizes="32px">→ 2x 永远不生效 - 如果真要配合
sizes(比如按钮在不同断点下宽度不同),必须改用w描述符:srcset="btn-32w.png 32w, btn-64w.png 64w",并确保sizes值与 CSS 实际渲染宽度一致
验证是否真加载了 @2x 图,别信 console.log(devicePixelRatio)
window.devicePixelRatio 返回 2 只说明设备支持高 DPI,不代表图片就加载了 @2x 版本。真正决定加载哪张图的是 HTML 结构和浏览器解析逻辑。
唯一可靠验证方式:
打开 Chrome DevTools → Network 面板 → 刷新页面 → 筛选 Img 类型 → 找到对应按钮图标 → 右键「Copy image src」→ 粘贴确认 URL 含 @2x 或 @3x。
- 模拟不同 DPR:DevTools → ⚙️ → Sensors → Device pixel ratio → 改为 1 / 2 / 3,然后 **硬刷新(Ctrl+Shift+R)**,普通刷新可能走缓存
- 注意检查
<img>是否被 CSS 强制设置了固定宽高(如width: 24px; height: 24px),这会导致 @2x 图被压缩失真,即使加载成功也模糊 - 确保父容器没设
overflow: hidden或max-width限制,否则高清图可能被裁剪
图标类图片最容易被忽略的三个细节
按钮图标体积小、复用率高,但适配稍有偏差就会明显失真。问题往往不出在 <picture> 写法,而在配套资源和样式。
- @2x/@3x 图必须是原尺寸导出:比如设计稿中按钮图标是 24×24px,那 @2x 就得是 48×48px,@3x 是 72×72px —— 不能靠 CSS 缩放 96×96px 图片来“凑”
- 必须加
max-width: 100%; height: auto,否则在弹性布局中可能被拉伸变形 - 不要依赖
<picture>自动 fallback:IE11 不支持srcset,所以<img src="btn@1x.png">的src必须指向可用的 @1x 图,且该图需能独立清晰显示



















