匹配顺序是自上而下取第一个media为true的,命中即停;type在media筛选后二次优先选择支持格式;sizes+srcset仅在选中的source内部生效,不影响source选择。

picture 中 <source></source> 的匹配顺序是自上而下找第一个真值
浏览器不会综合所有 <source></source> 做“最优解”,而是从第一个开始逐个检查 media 属性,一旦某个为 true,就立即选用它对应的资源,后续全部跳过。这和 CSS 里 @media 的层叠逻辑一致,但更严格——没有“覆盖”概念,只有“命中即停”。
常见错误现象:
- 写了
<source media="(max-width: 500px)"></source>在下面,<source media="(max-width: 800px)"></source>在上面 → 小屏永远走 800px 分支,500px 分支永远不会触发 - 多个
media条件重叠(比如同时写(min-width: 400px)和(min-width: 300px))→ 后者永远无效
正确做法:
- 按断点从窄到宽、或从宽到窄统一方向排列,避免交叉
- 移动端优先:把
(max-width: 480px)放最前,(min-width: 1024px)放最后 - 桌面端优先:把
(min-width: 1200px)放最前,(max-width: 768px)放最后(但需确保无遗漏区间)
sizes 和 srcset 的优先级不参与 <source></source> 选择
sizes + srcset 只在最终选中的那个 <source></source>(或 fallback <img>)内部起作用,用于从该 source 提供的候选集中挑一张最合适的图。它不参与“哪个 <source></source> 被选中”这个阶段的决策。
也就是说:<source></source> 决定“用哪一组资源”,sizes+srcset 决定“这一组里哪一张最配当前 DPR 和视口宽度”。两者分属不同层级。
容易混淆的点:
- 误以为
sizes="(min-width: 40em) 80vw, 100vw"会影响<source></source>匹配 → 实际上它只对紧邻的srcset生效 - 在
<source></source>上同时写media和sizes,却没配srcset→sizes被忽略(HTML 规范要求sizes必须与srcset成对出现)
type 属性的优先级高于 media
如果多个 <source></source> 都满足 media 条件,浏览器会优先选择支持的 type(如 image/avif),哪怕它排在后面。但这不是“真正意义上的优先级提升”,而是浏览器在匹配完 media 后的二次筛选:先筛出所有 media 为 true 的 <source></source>,再从中挑第一个能被当前浏览器解码的 type。
所以实际建议顺序是:
- 第一层:按
type降级(AVIF → WebP → JPEG/PNG) - 第二层:每种
type内部,再按media有序排列
示例结构:
<picture><source type="image/avif" srcset="hero-avif-400.avif 400w, hero-avif-800.avif 800w" sizes="(min-width: 640px) 800px, 100vw"><source type="image/webp" srcset="hero-webp-400.webp 400w, hero-webp-800.webp 800w" sizes="(min-width: 640px) 800px, 100vw"><source media="(min-width: 640px)" srcset="hero-jpg-800.jpg 800w, hero-jpg-1200.jpg 1200w" sizes="800px"><source srcset="hero-jpg-400.jpg 400w" sizes="100vw"><img src="hero-jpg-400.jpg" alt="英雄区主视觉"></source></source></source></source></picture>
注意最后一行 <img> 没有 srcset 或 sizes,它只是保底,不参与任何响应式计算。
fallback <img> 永远不参与媒体查询匹配
<img> 标签放在 <picture></picture> 最后,仅当所有 <source></source> 都不匹配(或类型都不支持)时才启用。它没有 media 属性,也不看 sizes,它的 src 就是最终兜底地址。
关键细节:
-
<img>必须存在,否则<picture></picture>在不支持的浏览器中会显示空白 - 即使你给
<img>加了srcset,它也不会被当作<source></source>处理;浏览器只认<source></source>元素的media/type -
<img>的alt是唯一影响 SEO 和无障碍的文本,务必写描述性内容,不能留空或写“图片”
最常被忽略的一点:很多人以为把 <source></source> 全部写成 media="(min-width: 0px)" 就能“强制走某一分支”,其实只要有一个 <source></source> 匹配成功,<img> 就完全不会加载——哪怕它带了 loading="eager"。这个边界很硬,没有妥协余地。










