srcset 里写的是像素密度(x 单位)或图片固有宽度(w 单位),需配合 sizes 中声明的页面占位宽度,由浏览器结合视口尺寸和设备 DPR 匹配最适源;sizes 缺失或不匹配会导致大图滥用。

srcset 里写的是什么,不是分辨率而是像素密度或视口宽度
很多人一看到 srcset 就默认它在“按屏幕 DPI 切图”,其实它支持两种语法:一种是带 x 的(如 1x, 2x),对应设备像素比;另一种是带 w 的(如 400w, 800w),对应图片源的**固有宽度**。浏览器会结合 sizes 中声明的**图片在页面中最终占位宽度**,再根据当前视口尺寸和设备 DPR,选出最匹配的源。
常见错误是混用两种单位却没配对好 sizes,比如写了 srcset="img-400w.jpg 400w, img-800w.jpg 800w" 却漏了 sizes,这时浏览器只能回退到 100vw,导致小屏也加载大图。
-
sizes必须存在才能让w单位生效,否则浏览器无法估算渲染宽度 - 写
sizes="(max-width: 768px) 100vw, 50vw"意味着:在 ≤768px 视口时,这张图占满整个视口宽;否则只占视口一半 - 如果图片实际被 CSS 压缩到 300px 宽,但
sizes写成100vw,而视口是 1200px,浏览器就会去选接近 1200w 的图——哪怕你根本用不上那么大
为什么加了 srcset 还是加载了最大图
核心原因通常是 sizes 值过于保守,或者未覆盖关键断点。浏览器不会“猜”你想要哪张图,它严格按 sizes 提供的占位宽度 + 当前 devicePixelRatio 查表匹配 srcset 中最接近的源。
例如你给一张卡片内嵌图写:sizes="(max-width: 480px) 90vw, (max-width: 768px) 45vw, 300px",但实际在 500px 宽的 iPad 上,它命中的是 45vw → 225px,若此时 srcset 只提供 320w 和 640w,浏览器可能选 320w;但如果 srcset 是 400w 400w, 800w 800w,它就只能选 400w——即使 225px 渲染宽度下 400w 已明显过剩。
立即学习“前端免费学习笔记(深入)”;
- 检查 DevTools 的 Network 面板,看
Request Headers里有没有Sec-CH-DPR或Width,没有说明浏览器没启用响应式选择逻辑 - 确保
sizes中的媒体查询与你的 CSS 布局真实一致,别信“大概差不多” - 不要省略单位:
sizes="50vw"合法,sizes="50"无效
img 标签必须同时有 src 和 srcset 才能降级兼容
src 不是可选项,它是所有浏览器都识别的兜底地址。如果只写 srcset,老浏览器(如 IE、旧版 Safari)会直接不显示图片,连 alt 文字都不触发。
更隐蔽的问题是:某些低版本 Android WebView 对 srcset 解析有 bug,会忽略整个属性,此时只有 src 起作用。所以 src 应该指向一个中等清晰度、体积适中的版本(比如 768w 或 800w),既不至于太糊,也不会拖慢首屏。
-
src的图不需要是最小的,但必须是“安全可用”的中间档 - 不要把
src指向1x图然后指望高 DPR 设备自动升格——没srcset就没升格 - 若用构建工具生成多尺寸图,记得把
src对应的那张也放进输出目录,否则上线 404
使用 w 单位时,sizes 的计算必须基于 CSS 渲染后宽度
这是最容易被忽略的一环:浏览器读取 sizes 是在 layout 阶段之前,它依赖的是你写的静态表达式,而不是运行时 JS 计算出来的宽度。如果你用 JS 动态改了图片容器宽度,但 sizes 是写死的,浏览器不会重新评估。
典型场景:模态框里的图片,在弹出后宽度才从 0 变为 500px,但 sizes="100vw" 在 DOM 插入时就被解析了,结果加载了整屏宽的图,哪怕模态框只占一半。
- 避免在动态容器中硬写
sizes,优先用 CSS 固定宽高比(如 aspect-ratio)+width控制,再配静态sizes - 真需要 JS 控制时,得用
picture+source+media,或者干脆用 JS 加载逻辑替代srcset - 测试时打开 Chrome 的 Device Toolbar,切换不同设备并刷新,别只靠缩放窗口——缩放不触发 DPR 变化
真正难的不是写对语法,而是把 sizes 和你实际 CSS 布局的宽度映射关系理清楚。很多项目卡在这一步,不是不会用,是不敢信自己写的 sizes 真的等于浏览器算出来的那个值。



















