picture标签匹配逻辑为“短路优先”,即从上到下逐条检查source,首个同时满足media和type的即被采用,后续全部跳过;顺序即优先级,需按设备能力由强到弱排列,断点互斥,type优先级高于media但不降级,img为必选fallback节点,srcset中w/x描述符仅在img中生效。

picture标签的匹配逻辑是“短路优先”,不是“最优优先”
浏览器不会综合评估所有 <source></source>,而是从上到下逐条检查,一旦遇到第一个同时满足 media(视口条件)和 type(格式支持)的 <source></source>,就立刻加载它的 srcset,后面所有 <source></source> 全部跳过。
这意味着顺序就是优先级 —— 写在最上面的规则拥有最高“话语权”,哪怕它只适用于 1% 的设备,只要匹配成功,宽屏、高 DPR、现代格式统统被拦在门外。
- 常见错误:把
media="(max-width: 767px)"放最前 → 所有手机、平板甚至部分折叠屏都命中这条,min-width: 1200px永远不执行 - 正确做法:按设备能力从强到弱排,例如
(min-width: 1440px) and (min-resolution: 2dppx)→(min-width: 1200px)→(min-width: 768px)→ 最后留max-width: 767px - 断点必须互斥:避免
max-width: 768px和min-width: 768px同时存在,768px 宽度会随机命中其一,行为不可控
type属性的优先级高于media,但不自动降级
type="image/avif" 这类格式声明不是“尽力而为”,而是硬性开关:浏览器只看自己是否原生支持该 MIME 类型。Chrome 支持 AVIF 就加载,Safari 15 前不支持就直接跳过整条 <source></source>,不会往下找 type="image/webp" 或 JPEG。
所以 type 必须配合兜底策略,不能指望它“链式降级”。
- 错误写法:
<source type="image/avif" srcset="a.avif"><source type="image/webp" srcset="a.webp"></source></source>→ Safari 用户直接跳过两条,落到<img src> - 推荐结构:把
type和media组合使用,例如<source type="image/avif" media="(min-width: 1200px)" srcset="hero-avif.jpg"></source>,再配通用 JPEG fallback - 服务器必须返回正确的
Content-Type,否则 Chrome 显示blocked:mime-type,静默失败
img标签不是可选装饰,而是强制终止节点
<img> 是 <picture></picture> 的唯一必选子元素,且必须带 src 和 alt。它不参与任何匹配逻辑,只在所有 <source></source> 都未命中时被动触发 —— 浏览器不会报错,也不会提示,页面就直接留白或显示占位符。
- 漏掉
src:整个图片区域为空,尤其在 iOS Safari 上更明显 -
<img>自闭合写法无效,必须写成完整闭合标签:<img src="fallback.jpg" alt="描述"> - 建议给
<img>也加srcset和sizes,尤其当 fallback 图也要适配 Retina 屏时,例如:<img src="fallback-1x.jpg" srcset="fallback-1x.jpg 1x, fallback-2x.jpg 2x">
srcset里的w和x描述符在picture中作用范围不同
<source></source> 中的 srcset 只负责提供一组候选图地址,浏览器不解析其中的 w 或 x 描述符;真正起作用的是最外层 <img> 的 srcset + sizes 组合 —— 它控制 DPR 和视口宽度下的分辨率选择。
也就是说:<source></source> 决定“用哪张构图”,<img> 的 srcset 决定“这张构图里用哪个分辨率版本”。
-
<source srcset="a-400w.jpg 400w, a-800w.jpg 800w"></source>→ 这些w值被忽略 - 必须写:
<img src="a-400w.jpg" srcset="a-400w.jpg 400w, a-800w.jpg 800w" sizes="(max-width: 600px) 100vw, 50vw"> - 混用
400w和2x在同一srcset中会导致整个值失效,回退到src
<source></source> 都没发出请求,问题一定出在语法(比如 media 缺括号)、顺序(窄屏规则挡住了宽屏),或者服务器没返回正确 MIME 类型。不要猜,先看 DevTools 的 Priority 和 MIME 列。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











