推荐方案:四种场景的写法
前九页逐个拆开了属性与浏览器的行为,本页把它们收拢成可以照抄的写法。场景按图片在页面中的位置与作用划分,而不是按属性划分:同一个 sizes="auto",在正文配图上是首选,在首屏主图上无效,在 object-fit: contain 的缩略图上反而多下载。
1 · 共同的底线
四种场景都遵守下面几条,理由分散在前面各页:
-
始终写
width与height,按src那张候选的真实像素尺寸。它们防止 CLS(尺寸与占位 §1),让懒加载按正确的位置判断(loading §3),并在sizes="auto"的contain: size下充当唯一的比例来源(sizes="auto" §2) - 分辨率切换放进
srcset的 w 描述符,不写成<source media>。浏览器保留在弱网降级、从缓存复用的裁量(picture 与 source §4) - 始终保留
src,指向一张中等尺寸的候选,作为不支持srcset的环境与爬虫的回退 alt描述图片传达的内容;装饰图写alt=""(其余属性 §1)
2 · 候选宽度的阶梯
每张图生成多少档、每档多宽,是写 srcset 之前要定的事。x 描述符与像素密度 §3 实测的选择规则是取不小于所需密度的最小一档,所以最坏情况出在所需宽度刚好比某一档多一点:浏览器只能拿下一档。相邻两档的宽度比为
时,最坏的像素冗余是
。
时最坏多下载 125% 的像素,平均情况远低于此; 时最坏是 4 倍。作者的判断是 1.5 左右是一个合理的折衷:档数再多,CDN 缓存的命中率随之下降,构建时的转码量随之上升,而节省的字节越来越少。阶梯的下端取最窄布局宽度,上端取最宽布局宽度乘以打算支持的最大 DPR。
最大 DPR 取 2 还是 3,是另一个判断。3x 屏上,2x 的图与 3x 的图在正常观看距离下差别很小,像素数却差 2.25 倍。对照片类的大图,把上端封在 2x 是常见的做法;对含细线与小字的图(图表、截图),3x 的清晰度差别更容易被察觉,可以保留。
3 · 首屏主图
<img src="hero-1280.jpg"
srcset="hero-640.jpg 640w, hero-960.jpg 960w, hero-1280.jpg 1280w,
hero-1920.jpg 1920w, hero-2560.jpg 2560w"
sizes="(min-width: 1280px) 1280px, 100vw"
width="1280" height="720"
fetchpriority="high"
alt="…">
主图是 LCP 的候选,目标是尽早发出请求、尽早拿到带宽。不写 loading,保持 eager,让 preload scanner 在解析 HTML 时就发现它;写 fetchpriority="high",不必等布局后才被提升。sizes 只能手写,eager 图上的 auto 无效,在 Chrome 154 里还会被当作
100vw(核对于 2026-09)。
主图若是 CSS 背景或由客户端脚本渲染,补一条 <link rel="preload" as="image">,imagesrcset 与 imagesizes 与上面的 srcset / sizes 逐字一致(优先级与解码 §2)。
4 · 正文配图
<img src="figure-960.jpg"
srcset="figure-480.jpg 480w, figure-720.jpg 720w, figure-960.jpg 960w,
figure-1440.jpg 1440w"
sizes="auto, (min-width: 752px) 720px, calc(100vw - 32px)"
width="960" height="640"
loading="lazy" decoding="async"
alt="…">
首屏以下的配图是 sizes="auto" 的主场。布局宽度由 CSS 决定,auto 取之即用;其后的手写列表只为不支持 auto 的浏览器保留,它们把 auto 当作无效项跳过。等到存量设备里不再有 Chrome 126、Firefox 150 与 Safari 27 之前的版本,回退部分可以删掉(核对于
2026-09)。
decoding="async" 在长文里意义不大,但在一次滚动带入多张大图时,能避免它们的解码挤进同一帧。一页里前几张图若落在首屏,从这个模板里去掉 loading="lazy",同时把 sizes 改回手写。
5 · 缩略图网格
<img src="thumb-320.jpg"
srcset="thumb-160.jpg 160w, thumb-240.jpg 240w, thumb-320.jpg 320w,
thumb-480.jpg 480w"
sizes="auto, (min-width: 1000px) 240px, calc(50vw - 24px)"
width="320" height="320"
loading="lazy" decoding="async"
style="aspect-ratio: 1; object-fit: cover"
alt="…">
网格里的缩略图通常统一裁成一个比例,由 aspect-ratio 与 object-fit: cover 完成。cover 下图面宽度与盒宽一致,auto 选图没有偏差。改用 object-fit: contain 时情况不同:sizes="auto" §3
的实测显示浏览器按盒宽选图,而 contain 的图面可能窄得多,此时应当按图面宽度手写 sizes,放弃 auto。
缩略图在所有断点上尺寸都相同时,x 描述符更简单:srcset="thumb-160.jpg 1x, thumb-320.jpg 2x",不需要 sizes。
6 · art direction 与格式
<picture>
<source media="(min-width: 900px)" type="image/avif"
srcset="wide-960.avif 960w, wide-1600.avif 1600w, wide-2400.avif 2400w"
sizes="100vw" width="1600" height="600">
<source media="(min-width: 900px)"
srcset="wide-960.jpg 960w, wide-1600.jpg 1600w, wide-2400.jpg 2400w"
sizes="100vw" width="1600" height="600">
<source type="image/avif"
srcset="square-480.avif 480w, square-800.avif 800w, square-1200.avif 1200w"
sizes="100vw">
<img src="square-800.jpg"
srcset="square-480.jpg 480w, square-800.jpg 800w, square-1200.jpg 1200w"
sizes="100vw" width="800" height="800" alt="…">
</picture>
<picture> 里有两个互相正交的维度:画面(media)与格式(type)。按「画面在外、格式在内」排列,每个画面分支内先列新格式、后列回退格式,<source> 的数目等于画面数乘以格式数。每个画面分支写自己的 width /
height,否则非默认分支在加载前按 <img> 的比例占位(picture 与 source §2)。
只做格式协商、不做 art direction 时,去掉 media 即可,结构退化为一个 AVIF <source> 加一个 JPEG <img>。图片 CDN 能按请求头 Accept(Chrome 154 发出的是
image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8)做服务器端协商时,HTML 里连这一层 <source> 也可以省掉,只是换来的代价是缓存必须按 Vary: Accept 区分(核对于 2026-09)。
7 · 不需要这套机制的图
图标、Logo、简单插画优先用 SVG,一个文件覆盖所有密度与尺寸,本系列的机制一概不需要。尺寸固定的位图图标用 x 描述符。装饰性的纹理与渐变能用 CSS 画出来的,不必做成图片。响应式图片的全部复杂度只该花在照片与复杂位图上——它们才是页面字节的大头。