media属性必须写在<source>标签内,浏览器按从上到下线性扫描并短路匹配,首个media为true的<source>即被加载,后续全部跳过;<picture>上直接写media会被忽略,且<img>为必需fallback节点,须含src和alt。

media属性必须写在里,且顺序决定匹配结果
浏览器对 <source> 是线性扫描、短路匹配:从上到下检查 media,遇到第一个为 true 的就加载对应资源,后面的全跳过。这不是“最优匹配”,而是“首个命中”。
常见错误包括:
-
media写在<picture>标签上(如<picture media="(max-width:768px)">)→ 浏览器直接忽略 -
media="(max-width: 768px)"缺括号 → 写成media="max-width: 768px"就静默失效 - 断点重叠,比如同时存在
(min-width: 768px)和(max-width: 768px)→ 768px 宽度行为不可控,不同浏览器可能表现不一 - 顺序反了:把
max-width: 767px放最前 → 所有设备都走这条,宽屏图永远不加载
✅ 推荐写法(从宽到窄):<source media="(min-width: 1200px)" srcset="hero-desktop.jpg"><source media="(min-width: 768px)" srcset="hero-tablet.jpg"><source media="(max-width: 767px)" srcset="hero-mobile.jpg">
<img>不是可选的,是强制 fallback 节点
<img> 必须存在,且必须带 src 和 alt,不能自闭合。
原因很实际:
立即学习“前端免费学习笔记(深入)”;
- 不支持
<picture>的旧浏览器(如 IE)会直接忽略整个<picture>,只渲染<img> - 所有
<source>的media都不匹配时(比如视口宽度刚好卡在断点缝隙),浏览器会 fallback 到<img src> - 屏幕阅读器只读
<img>的alt,<source>不参与可访问性
❌ 错误写法:<img />、<img>、<img alt="描述">(缺 src)
✅ 正确写法:<img src="fallback.jpg" alt="首页横幅">
type 属性和服务端 MIME 类型必须严格一致
type 声明的是“我期望你返回什么类型”,不是“我随便试试”。浏览器看到 type="image/webp",就会检查服务器响应头里的 Content-Type 是否为 image/webp —— 大小写、拼写、空格,差一点就静默丢弃该 <source>。
常见问题:
-
type="webp"或type="image/jpg"→ 非法值,被忽略 - 服务器返回
Content-Type: image/jpeg,但<source>写了type="image/jpeg"→ 注意jpeg和jpg在 MIME 类型中不等价,标准是image/jpeg - Network 面板看到
blocked:mime-type或 404 → 基本就是type和服务端配置没对齐
✅ WebP 兼容推荐结构:<source type="image/webp" srcset="hero.webp"><source type="image/jpeg" srcset="hero.jpg"><img src="hero.jpg" alt="...">
srcset 和 sizes 只在 <img> 上生效,别混进 <source>
srcset 中的 x 描述符(如 2x)只在 <img> 上起作用;<source> 里的 2x 完全被浏览器无视。DPR 适配必须交给 <img> 的 srcset。
同样,sizes 只能写在 <img> 上,它配合 w 描述符告诉浏览器“这张图在页面中大概占多宽”。写在 <source> 里会被完全忽略。
容易踩的坑:
- 在
<source>的srcset里写photo@2x.jpg 2x→ 无效 - 给
<img>加了sizes却没配w描述符 →sizes被当成无用字段 - 混用
w和x(如srcset="a.jpg 400w, b.jpg 2x")→ 整个srcset解析失败,回退到src
✅ 合理搭配:<source media="(max-width: 480px)" srcset="small.jpg"><img src="small.jpg" srcset="small.jpg 1x, small@2x.jpg 2x" sizes="100vw">
真正麻烦的不是语法本身,而是当所有规则都看似正确时,你得打开 Network 面板看请求是否发出、状态码是否 200、响应头 Content-Type 是否匹配、<img> 是否真的被渲染出来——这些细节一旦漏掉一个,<picture> 就会安静地退化成一张固定图。



















