网站与开发 / CLEARBYTE

响应式图片:理解 srcset、sizes 与设备像素比

srcset 列出可用图片文件。使用宽度描述符时,sizes 说明图片预期占用的 CSS 像素宽度,浏览器结合设备像素比及自身策略选择资源。实际布局仍由 CSS 决定。

本指南内容

图片看起来正常,并不代表下载量合理。页面可能下载远超显示需求的像素,也可能把小图拉伸到高像素密度屏幕上。响应式标记把生成的图片文件与页面中的显示空间联系起来,两者描述同一布局时才真正有效。

先从一个实际组件和几个有意义的图片尺寸开始。本文示例的内容栏最大宽度为 800 CSS 像素,窄屏左右各留 16 像素。所有候选图片使用相同构图,宽高比均为 4:3。

区分源文件像素、CSS 像素与 DPR

宽 800 像素的图片,不必在页面上占据 800 CSS 像素。浏览器可以把它显示在宽 400 CSS 像素的区域内。设备像素比为 2 时,这个区域横向约对应 800 个设备像素。这是分辨率规划关系,浏览器仍有权决定最终加载哪个资源。

先计算示例组件的显示宽度:取 800 与视口宽度减去 32 两者中的较小值,再乘以 DPR,得到可参考的源图片宽度。如果图片只占狭窄内容栏,就不应直接把整个视口宽度乘以 DPR。

为最大 800 像素内容栏规划源图片宽度
视口宽度CSS 显示宽度DPR目标源宽度
3923601360 像素
3923602720 像素
10248001800 像素
102480021600 像素

布局宽度变化时,使用宽度描述符

w 描述符表示文件本身的像素宽度,既不是媒体查询断点,也不能随意填写。sizes 告诉浏览器当前布局预期的显示宽度。下面的标记在视口不小于 832 CSS 像素时使用 800 像素显示区域;更窄时则扣除两侧边距。

示例 CSS 也是约定的一部分。如果以后把组件放进半宽网格,应同步修改 sizes。保留旧的全宽描述,可能让浏览器选中不必要的大文件。准确的 sizes 是对真实布局的描述,不是热门屏幕宽度的集合。

<img
  src="/images/workspace-800.webp"
  srcset="/images/workspace-400.webp 400w,
          /images/workspace-800.webp 800w,
          /images/workspace-1600.webp 1600w"
  sizes="(min-width: 832px) 800px, calc(100vw - 32px)"
  width="1600" height="1200"
  alt="A desk with a monitor and an open notebook"
  style="display:block;width:calc(100vw - 32px);max-width:800px;height:auto;margin-inline:auto"
>

先估算候选资源,再检查实际选择

在宽 392、DPR 为 2 的视口中,显示区域为 360 CSS 像素,目标源宽度为 720。因此,在给定文件中,800w 是合理的预期选择。宽屏 DPR 为 2 时,目标为 1600。计算解释了选择的输入,但不能强制浏览器一定下载某个候选文件。

浏览器还可能考虑其他因素。缩小窗口后,它可能继续使用已经下载的大图。测试时应先选好设备设置,再使用新页面环境或重新加载,然后在开发者工具中查看最终图片 URL 与传输字节。反复缩放同一个已预热页面,容易得出错误结论。

候选列表也要求构建流程真正生成对应文件。生成 400、800、1600 像素版本,检查画质并确认每个 URL 都返回图片。不能把同一个 1600 像素文件复制改名,再给它们贴上不同的 w 标签;这种做法没有降低真实下载或解码成本。

  • 检查元素的实际渲染宽度,不要默认它等于视口宽度。
  • 把 currentSrc 选中的地址与网络面板中的响应对照。
  • 核查文件尺寸、响应类型、缓存状态和传输字节。
  • 在窄屏和宽屏下分别检查 DPR 1 与 DPR 2。
  • 观察加载前后是否出现横向溢出或布局移动。

固定显示尺寸的图片可使用密度描述符

对于始终以固定宽度显示的小标志,可以改用 x 描述符。例如显示宽度为 120 CSS 像素时,提供宽 120 的 1x 文件和宽 240 的 2x 文件。这些是同一固定显示尺寸的不同分辨率版本;不要在同一个 srcset 中混用 x 与 w。

改变裁剪属于另一个设计问题。移动端需要脸部特写,而桌面端需要宽场景时,可通过 picture 和适当的媒体条件实施美术指导。本文主例使用相同构图,仅改变分辨率。替代文本应描述读者真正获得的有意义内容,而不是重复文件名或候选宽度。

<img src="/images/mark-120.png"
     srcset="/images/mark-120.png 1x, /images/mark-240.png 2x"
     width="120" height="120" alt="Example project mark">

同时规划宽高比与加载时机

width 和 height 属性帮助浏览器在图片到达前按宽高比预留空间。CSS 改变显示宽度后,它们并不强迫图片维持原始 CSS 尺寸。示例宽高比为 4:3,因此显示宽 800 时高 600,显示宽 360 时高 270。保持比例可以避免图片变形。

长页面下方图片适合延迟加载,但不应不分位置地推迟首屏重要图片的请求。应根据组件使用位置决定。候选分辨率减少多余像素,合适的压缩、格式及加载策略则分别处理其他开销,不能互相代替。

原始图像内存与网络文件大小也不同。压缩后的 WebP 文件可能很小,解码后的像素缓冲区却大得多。图像内存计算器使用解码尺寸,网络成本则应测量实际压缩文件,不能仅凭像素数量推断字节。

发布前检查组件与生成文件是否一致

把布局规则和图片生成规则作为一个明确约定保存。记录候选宽度、裁剪、比例、压缩质量和 sizes 表达式,便于以后一起修改。最大宽度从 800 改为 1000 像素时,应重新审查候选资源,而不是只改样式。

发布前检查回退 src、所有 srcset 地址、替代文本和预留空间。用 CSS 到设备像素计算器复现自己的显示宽度和 DPR,再用宽高比计算器规划高度。若边距是固定 CSS 值,就不要只写 100% 作为 sizes 来代替真实表达式。

组件评审应说明测试时的页面布局,而不仅列出设备名称。同一手机横屏、竖屏或浏览器缩放状态可能产生不同显示宽度。保留实际截图和网络记录,后续修改时才能比较是否只是候选变化,还是布局规则已经变化。测试中命中缓存也要明确记录,避免把缓存带来的零传输误认成图片压缩效果。

常见问题

sizes 会改变图片的 CSS 宽度吗?

不会。使用宽度描述符时,它为资源选择描述预期显示区域。实际布局由 CSS 控制,两者应保持一致。

缩小窗口后为什么仍使用大图?

浏览器可能复用已经下载的资源。应在目标视口和 DPR 下重新加载,再检查选中的地址及网络传输,不要只观察一次窗口缩放。

2x 图片的文件大小总是两倍吗?

不是。宽高都翻倍会产生四倍像素,但编码字节还取决于画面内容、格式和压缩质量。应实际测量生成文件。

来源与定义

方法核验日期: