<picture>中source按顺序匹配,首个media为true的立即生效,其余跳过;所有source不匹配时回退至内部<img>的src;media属性仅在插入DOM或resize时评估,不响应JS动态修改。

picture 的 source 必须写在 <picture> 内部,且顺序决定匹配结果
浏览器不会“综合判断”所有 source,而是从上到下扫描,**第一个 media 为 true 的就立即采用,其余全部跳过**。这和 CSS 的层叠不同,是短路逻辑。
- 宽屏断点要放前面,比如
media="(min-width: 1200px)";窄屏兜底放最后,比如media="(max-width: 767px)" - 避免重叠断点:写
max-width: 768px和min-width: 768px,在恰好 768px 宽时行为不可控(只认第一个) - 单位不能省:
768是非法媒体查询,必须写成768px - 如果所有
source都不匹配,浏览器会回退到末尾的<img>—— 这个元素不是可选的,漏掉或没写src就是空白
source 的 media 属性只响应视口变化,不响应 class 或 JS 修改
你给 source 元素动态改 media 属性(比如用 JS 设置 el.media = "(min-width: 900px)"),浏览器**不会重新评估匹配**。它只在元素首次插入 DOM 或窗口 resize 时触发匹配逻辑。
- 常见误操作:JS 切换主题后直接改
source.media,但图片没变 —— 因为浏览器根本不监听这个属性变化 - 真正生效的方式只有两种:重建整个
<picture>结构,或手动触发<img>的src更新(比如img.src = img.src强制重载) - 更稳妥的做法是:用
matchMedia()监听断点,并在回调里显式切换<img>.src,绕过source匹配机制
srcset 在 source 和 <img> 中作用完全不同
source 的 srcset 只负责提供「哪张图」,而 <img> 的 srcset 才负责「这张图的哪个分辨率版本」。混用会导致 DPR 适配失效。
-
<source srcset="a@2x.jpg 2x">→ 浏览器完全忽略2x,只当普通路径用 - 正确做法:
<source media="(max-width: 480px)" srcset="small.jpg">+<img src="small.jpg" srcset="small.jpg 1x, small@2x.jpg 2x"> - 如果用了
w描述符(如photo-400w.jpg),sizes必须写在<img>上,且值要和实际 CSS 布局一致;写在<source>里会被无视
节日换肤等非标准条件,别硬塞进 media
media 只支持原生媒体特性(如 width、orientation、prefers-color-scheme),**不支持自定义状态**。春节红、圣诞绿这类主题无法靠 media="(theme: christmas)" 实现。
立即学习“前端免费学习笔记(深入)”;
- 强行用 JS 改
source.media并不能触发重选,且破坏语义和可访问性 - 推荐方案:预置多组
<picture>,用 class 控制显隐(如theme-christmas显示对应<picture>,其余display: none) - 或者只留一个
<picture>,但由 JS 直接更新内部<img>.src和.alt,确保 fallback 和可访问性不丢
<picture> 是声明式选择,不是运行时控制器;所有“动态”需求都要落在 JS + CSS 配合上,而不是试图让 media 理解业务逻辑。



















