sizes 属性必须配合 srcset 使用,用于告知浏览器图片在不同视口下的渲染宽度,从而选择最合适的图片资源;缺失 sizes 会导致浏览器默认按 100vw 选图,造成移动端加载大图浪费带宽。

没写 sizes,浏览器只能猜宽度
浏览器拿到 srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w" 后,并不会自动知道“这张图在页面里实际占多宽”。它默认按 100vw 算——哪怕你的 CSS 把 img 压到了 320px 宽,它也可能去拉 large.jpg。结果就是:移动端加载了本不需要的大图,带宽浪费、解码卡顿。
真正起作用的是 sizes,它把 CSS 布局逻辑“翻译”给浏览器:
-
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"—— 意思是:小屏占满视口,中屏占一半,大屏固定占 1/3 视口宽 - 浏览器结合当前视口宽度 +
sizes计算出“这张图渲染时需要的像素宽度”,再从srcset里挑最接近且不小于该值的资源 - 没
sizes,w单位就形同虚设;只写sizes不写srcset,也没候选图可选
sizes 写错导致首屏加载大图
常见错误是把 sizes 写成和 CSS 完全无关的值,比如硬写 sizes="50vw",但实际布局中图片在 768px 断点下只占 300px(约 39vw)。浏览器按 50vw 算,选了 800w 图,而其实 400w 就够用。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 打开 DevTools → Elements → 找到
img标签,看它的 computed width,再换算成 vw(比如 300px / viewportWidth × 100) - 对照你实际写的 CSS 媒体查询,把每个断点下的占比写进
sizes,例如:sizes="(max-width: 480px) 100vw, (max-width: 768px) 40vw, 25vw" - 别抄别人模板,尤其别照着设计稿“理想宽度”写——要测真实渲染宽度
为什么 sizes 不能靠 JS 动态生成
浏览器在 HTML 解析阶段就要决定加载哪张图,此时 CSS 还没完全解析、JS 更没执行。你用 document.querySelector('img').setAttribute('sizes', ...) 是无效的——请求早已发出。
这意味着:
-
sizes必须是静态 HTML 属性,不能依赖运行时计算 - 响应式布局若用 JS 控制容器宽度(如 ResizeObserver 动态改 class),
sizes就无法同步适配,应改用 CSS 媒体查询驱动的布局 - 服务端渲染(SSR)场景下,
sizes要基于用户 UA 或设备特征预判,但不如客户端媒体查询可靠,慎用
配合 width/height 防止布局跳动
sizes 解决的是“加载哪张图”,但不解决“图没加载完时页面怎么预留空间”。如果只写 sizes 不设 width 和 height,浏览器仍不知道宽高比,图片加载前高度为 0,一渲染就推挤下方内容。
正确做法:
- 在
img标签上写原始像素尺寸:width="1200" height="800"(不是 CSS 中的显示尺寸) - 再用 CSS 控制显示大小,例如
width: 100%; height: auto;,浏览器会按比例缩放 - 现代方案可用
aspect-ratio: 1200 / 800,但 Safari 15.4 以下需用padding-top技巧降级
这一步常被忽略,但它直接影响用户感知的“卡顿”——不是网络慢,而是布局重排闪了一下。


















