← 返回题目列表

srcset、sizes 和 picture 如何实现响应式图片?

中等 第 24 / 28 题 更新于 2026/07/29
HTML响应式图片性能优化WebP

简化版

srcset 提供多个图片候选,sizes 告诉浏览器图片在不同视口下预计占多宽,浏览器结合设备像素比、网络等因素选择资源;picture 则用多个 source 做格式或美术方向切换。src 必须保留作默认和兼容回退,同时应设置尺寸避免布局偏移。

详细版

同一画面不同分辨率应使用 srcset 的宽度描述符,如 480w960w,并用 sizes 描述布局槽位;固定显示尺寸的高密度图也可使用 1x2x。最终选择权属于浏览器,开发者不能假定某一候选必被下载。

若小屏需要裁剪成竖图,或希望优先 AVIF、失败后回退 WebP/JPEG,应使用 <picture>。浏览器从上到下选择第一个媒体条件和 MIME 类型都支持的 <source>,内部 <img> 仍负责语义、替代文本、尺寸和加载行为。

图片优化还需配合正确压缩、width/heightaspect-ratio、首屏加载优先级和非首屏懒加载,不能只添加一组候选 URL。

完整版教学

一、响应式图片解决带宽和清晰度的矛盾

一张宽 2400px、大小 900KB 的横幅在手机上可能只显示 360px 宽,直接下载原图会浪费大量流量。反过来只提供 480px 图片,在桌面高密度屏上放大到 1000px 又会模糊。响应式图片让浏览器在“足够清晰”和“传输更小”之间选择。

CSS 槽位宽度 × 设备像素比 ≈ 所需资源像素宽度
360px × 2 DPR = 720px

浏览器还可能参考节流、缓存和自身策略,所以这个公式是选择依据而不是强制命令。开发者负责给合理候选,不应通过 JavaScript 猜设备并替换 URL。

二、宽度描述符必须与 sizes 配合

480w 表示资源自身约宽 480 像素,不代表它显示为 480pxsizes 则描述在媒体条件下图片占据的 CSS 槽位宽度,浏览器在布局 CSS 尚未全部完成前就能据此预加载合适资源。

<img
  src="/photo-960.jpg"
  srcset="/photo-480.jpg 480w,
          /photo-960.jpg 960w,
          /photo-1440.jpg 1440w"
  sizes="(max-width: 600px) 100vw, 50vw"
  alt="海边日落"
  width="1440"
  height="900">

390px 宽、DPR 为 2 的手机上,槽位约为 390px,目标接近 780px,浏览器可能选择 960w。在 1200px 桌面上槽位是 600px,DPR 为 1 时也可能选择 960w,因为它是首个足够覆盖目标的候选。

三、密度描述符适合固定槽位

如果头像始终以 64 × 64 CSS px 显示,可以用 1x2x3x 表达不同设备像素密度。密度描述符与宽度描述符不能混在同一个 srcset 中。

<img
  src="/avatar-64.png"
  srcset="/avatar-64.png 1x, /avatar-128.png 2x, /avatar-192.png 3x"
  width="64"
  height="64"
  alt="用户头像">

DPR 为 2 的屏幕通常选 128px 资源,正好用四个设备像素绘制一个 CSS 像素区域。若图片槽位会随布局显著变化,应回到 w + sizes,否则密度信息无法描述宽度变化。

四、picture 负责格式协商和美术方向

picture 本身不渲染图片,它给内部 img 提供候选来源。浏览器从上到下检查 source,适合用来优先选择 AVIF/WebP,或在窄屏展示重新裁剪的主体图。

<picture>
  <source media="(max-width: 600px)" srcset="/hero-portrait.avif" type="image/avif">
  <source srcset="/hero-wide.avif" type="image/avif">
  <source srcset="/hero-wide.webp" type="image/webp">
  <img src="/hero-wide.jpg" width="1600" height="900" alt="讲师在白板前授课">
</picture>

格式切换保持同一内容,只改变编码;美术方向切换会改变裁剪、构图甚至宽高比。后者必须确认各版本仍传达同样的 alt 语义,必要时为不同布局预留正确比例。

五、尺寸属性是防止 CLS 的关键

现代浏览器会根据 widthheight 推导固有宽高比,在图片到达前预留空间。若一张最终高度 400px 的图片下载后突然把正文推下 400px,会造成明显累计布局偏移。

配置下载前空间风险
无尺寸信息通常为 0图片到达后跳动
width + height按比例预留最稳定
CSS aspect-ratio按指定比例预留适合容器驱动
只写固定高度可能拉伸需搭配宽度与 object-fit

HTML 尺寸描述的是比例基础,CSS 仍可设置 max-width: 100%; height: auto 让图片响应式缩放。二者并不冲突。

六、首屏和非首屏的加载策略不同

首屏主图通常是 LCP 候选,应直接出现在 HTML 中,避免 loading="lazy",必要时使用 fetchpriority="high"。视口下方图片可用原生懒加载减少初始请求,但过度懒加载会让用户滚动时看到空白。

原图 900KB → AVIF 260KB,节省 640KB
4G 实际 1.6MB/s 时,纯传输时间约少 400ms

候选数量也不是越多越好,每多一个版本都增加构建和存储成本。常见做法是按真实布局挑 3~5 个关键宽度,再用性能数据检查命中和浪费情况。

记忆钩子:srcset 给菜单,sizes 报桌子有多宽,浏览器点菜;picture 则先决定今天进哪家餐厅。

七、常见误区与追问

  • 误区:srcset 会让浏览器总是选择最接近的文件。 浏览器拥有最终策略,缓存、DPR、网络和节省流量设置都可能影响选择。
  • 误区:写了 srcset 就不需要 src src 是默认候选和旧环境回退,也是 img 的基础资源。
  • 误区:所有图片都应该懒加载。 首屏 LCP 图片懒加载会延后发现与请求,反而恶化性能。
  • 追问:为什么 sizes 写错会浪费流量? 浏览器会按错误槽位估算需求,例如实际 50vw 却写 100vw,可能下载接近两倍宽的资源。
  • 追问:CSS 背景图能用 picture 吗? 不能直接使用,但可通过 image-set() 和媒体查询提供不同密度或格式候选。
  • 追问:alt 应写文件内容还是用途? 应表达图片在当前上下文中的等价信息;纯装饰图片通常使用空 alt=""

八、加强记忆

先判断需求:同一构图只差清晰度,用 srcset;槽位随视口变化时再准确写 sizes;构图或编码格式需要切换,用 picture。用“槽位宽度乘 DPR”估算候选范围,例如 390 × 2 ≈ 780px,但把最终选择留给浏览器。最后补齐 src、替代文本和宽高比例,并把首屏 LCP 与下方图片分开制定加载策略,响应式图片才同时做到清晰、省流量、无跳动。