x描述符是浏览器根据DPR自动选图的关键机制,浏览器依据window.devicePixelRatio匹配srcset中不小于该值的最接近x项,且仅在<img>标签中生效;<source>的media属性用于按宽度筛选候选图,二者结合实现带宽与分辨率双重优化。

<source> 的 media 属性判断 + 对 <img> 的 srcset 中 x 描述符的自动选择。
浏览器如何根据 DPR 选图:x 描述符才是关键
srcset 中的 1x、2x、3x 是唯一被浏览器用来直接映射设备像素比(DPR)的机制。
- 浏览器读取当前设备的 window.devicePixelRatio(比如 iPhone 14 Pro 返回 3),然后在 srcset 列表中找最接近且不小于该值的 x 项
- 如果没有匹配项(如只有 1x, 2x 但 DPR=3),会退而求其次选最大的那个(2x)
- 这个过程完全自动,不依赖 JavaScript,也不受 <picture> 容器影响
常见错误:把 2x 写在 <source> 的 srcset 里却指望它按 DPR 切换
- 浏览器会忽略带
media的<source>中的x描述符——它只认<img>的srcset - 正确写法必须把
1x/2x/3x放在末尾的<img>标签里
为什么 picture 要配合 media + srcset 才能兼顾宽度和 DPR?
单靠x 描述符只能解决“同一尺寸下该用多高分辨率”,但无法解决“小屏不该加载大图”这种带宽浪费问题。
所以需要分层控制:
-
<source media="(max-width: 480px)">先筛出小屏设备,限定候选范围 - 这个
<source>的srcset可以只提供small@1x.jpg 1x, small@2x.jpg 2x—— 小图 + 高密度 - 另一个
<source media="(min-width: 481px)">提供大图的1x/2x/3x版本 - 最后的
<img>的srcset必须包含所有 fallback 组合(不能空着)
注意:<source> 不匹配时,浏览器不会尝试降级到其他 <source>,而是直接跳到 <img> —— 所以 <img> 的 srcset 必须覆盖最差兼容场景(比如只支持 1x 的旧浏览器)。
容易被忽略的三个硬性规则
-
<source>必须写在<img>前面,否则整个<source>被忽略 -
srcset中不能混用w和x(例如photo.jpg 400w, photo@2x.jpg 2x是非法的) -
<img>的src属性不可省略,它是所有不支持srcset的浏览器(如 IE)的唯一入口
验证是否生效的最快方式:打开 Chrome DevTools → Network → 刷新页面 → 看图片请求的文件名;再用 Device Toolbar 切换 iPhone 12(DPR=3)和 Nexus 5(DPR=3)对比加载路径——如果始终是 @1x.jpg,大概率是 <img> 的 srcset 没写对,或者 <source> 的 media 条件全部未命中。
真正的复杂点不在语法,而在图片资源准备:你得按比例生成 @1x、@2x、@3x 三套图,且每套都要适配不同断点下的尺寸约束。漏一套,DPR 切换就断档。



















