⭐ 推荐:社区规则条款 V1.0

`srcset` 和 `sizes` 计算。

周末
周末 萌新站长
发布于 2026-10-16 17:35 ·4 浏览 ·0 回复
内容摘要

浏览器按 sizes 匹配得到插槽宽度,乘以 DPR 算出目标宽度,再从 srcset 中选不小于目标宽度的最小候选,全部不足则取最大;省略 sizes 按 100vw,固定容器宜用 px,随视口比例变化用 vw,w 与 x 不应混用。

结论:浏览器不会读你的页面布局再去挑图,它只按 sizes 声明的「显示宽度(CSS 像素)」× 设备像素比(DPR)算出一个目标像素宽度,然后从 srcset 里挑第一张大于等于这个宽度的图;没有更大的,就取最大的那张。

srcset 和 sizes 到底是怎么算出下哪张图的?

结论:选图是一个三步计算题——读 sizes 得到插槽宽度(slot size),乘 DPR 得到目标宽度,再在 srcset 里做「最小的够用者胜出」选择。

具体流程:

  1. 浏览器布局时,把 sizes 里的媒体条件(media condition)从左到右逐条匹配,取第一条为真的长度值;全部不匹配时用最后那个纯长度值(不带条件的兜底项)。
  2. 这个长度就是插槽宽度,单位是 CSS 像素。如果整个 sizes 都省略,默认值等价于 100vw。
  3. 插槽宽度 × DPR = 目标宽度。DPR 是设备像素比,iPhone 常见 3,多数安卓旗舰 2.75~3.5,普通 1× 显示器为 1。
  4. 在 srcset 的 w 候选里,选「宽度 ≥ 目标宽度」中最小的一张;若所有候选都小于目标宽度,选最大的那张。

举一个能对得上号的算例

结论:同一个 sizes,DPR 不同,下载的文件可能相差两档,这就是响应式图片省流量的全部来源。

页面视口宽 1440 CSS 像素,图片所在容器实际宽 720 CSS 像素,标记写成:

<img src="a-800.jpg"
     srcset="a-400.jpg 400w, a-800.jpg 800w, a-1200.jpg 1200w, a-1600.jpg 1600w"
     sizes="(max-width: 600px) 100vw, 50vw"
     alt="示例">
  • 视口 1440px,1440 > 600,命中 50vw,插槽宽度 = 1440 × 0.5 = 720 CSS 像素。
  • DPR = 1 时目标宽度 720,候选里最小的 ≥ 720 是 800w,浏览器下载 a-800.jpg。
  • DPR = 2 时目标宽度 1440,最小的 ≥ 1440 是 1600w,浏览器下载 a-1600.jpg。
  • 如果 srcset 最大只到 1200w,那张 1600w 不存在,DPR = 2 时会退而选 1200w,图片会被轻微放大,这是可接受的取舍。

把 sizes 删掉会怎样?插槽宽度按 100vw 算,视口 1440px、DPR = 2 时目标宽度 2880,浏览器直接把最大的 1600w 拉下来。在小容器里放图却漏写 sizes,是最常见的流量浪费原因。

sizes 里写 50vw 和写 720px 有什么区别?

结论:50vw 是随视口变化的动态值,720px 是固定值;只有图片宽度真的与视口成固定比例时,才该用 vw。

如果图片在固定 max-width: 720px 的容器里,视口从 800px 变到 2000px 图片始终是 720 CSS 像素,此时写 sizes="720px" 最准确,写 50vw 会在视口 2000px 时算出 1000px,白白升级一档。

三个实际写法:

  • 要考虑内边距时用 calc():sizes="(min-width: 1024px) calc(100vw - 320px), 100vw"。
  • sizes 里的长度不能用百分比,sizes="50%" 无效并会被当作语法错误处理,请改用 vw 或 px。
  • 100vw 包含滚动条宽度(桌面端通常 15px 左右),会比内容区实际宽度略大,敏感场景用 calc(100vw - 15px) 或直接用固定值。

srcset 用 w 还是 x?能混用吗?

结论:w 描述符必须配 sizes,x 描述符不需要;两者写在同一个 srcset 里会让整个 srcset 失效。

w 表示图片的固有像素宽度,语义是「我有多宽」,由带 sizes 的公式去匹配。x 表示像素密度倍数,写法 a.jpg 1x, a@2x.jpg 2x,浏览器直接用当前 DPR 对照选择。两者混写(a.jpg 400w, b.jpg 2x)会被整体丢弃,退回只用 src。都不写描述符时,每个候选默认按 1x 处理。

用 picture 或 preload 时要注意什么?

结论:<picture> + <source media> 只用 media 选源,不需要 sizes;preload 想要不重复下载,imagesizes 必须和 <img> 上的 sizes 完全一致。

用 <link rel="preload" as="image" imagesrcset="..." imagesizes="..."> 提前拉图时,如果 imagesizes 和 img 的 sizes 不一致,浏览器会按两套公式各选一张,结果是同一张图下两次。另外,懒加载场景可以使用 sizes="auto",让浏览器先按占位尺寸、等布局完成后再用真实宽度计算,避免为未知宽度硬写一个估算值。

收束一下:sizes 描述显示宽度,srcset 描述可选资源,DPR 负责把前者换算成后者要匹配的目标宽度,加点缓存策略,这套公式就能稳定产出「刚好够清晰、不过量下载」的图片。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2193.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~