浏览器按dom顺序线性解析,首个同时满足media匹配和type校验的即被选用,后续全部跳过;缺括号、顺序错、type与content-type不一致或路径错误均导致静默失效。

浏览器怎么决定用哪个?顺序即规则
浏览器对 <source></source> 的解析是线性、短路、不可回溯的:从上到下逐个检查,遇到第一个同时满足 media(如果写了)和 type(如果写了)的 <source></source>,就立即加载它的 srcset 或 src,后面所有 <source></source> 和 <img> 的 srcset 都被跳过——哪怕后面的条件更“精确”或分辨率更高。
常见错误包括:
-
media="(max-width: 768px)"写成media="max-width: 768px"(漏括号)→ 条件永远为 false,整条被忽略 - 把手机断点
media="(max-width: 767px)"放在最上面 → 所有宽度 ≤767px 的设备都命中它,平板/桌面规则永远不会执行 -
<source></source>缺media也缺type→ 浏览器直接跳过,不报错也不警告
为什么加载失败却不报错?静默跳过的三类原因
<source></source> 匹配失败时,浏览器不会抛异常、不写 console、不触发 error 事件——它只是安静地往下走,直到找到可用资源。真正出问题的地方往往藏在三个层面:
-
路径或网络层:src 指向 404、大小写错误、跨域未配 CORS、或本地用
file://协议 → 全部静默跳过;建议逐个在新标签页打开 src 验证可访问性 -
服务端响应头:
type="image/webp"但服务器返回Content-Type: image/jpeg→ Safari/Chrome 直接跳过,不尝试解码 -
DOM 结构错误:把
<source></source>套在<div> 里、或放在 <code><img>后面 → 浏览器认为该<source></source>不合法,不参与匹配type 属性不是可选的“提示”,而是 MIME 类型校验开关
在
<picture></picture>中,type不是用来“建议格式”的,而是强制参与协商的校验项:浏览器会比对服务器实际返回的Content-Type响应头,必须逐字符一致才考虑加载。比如:-
type="image/webp"要求响应头是Content-Type: image/webp;写成image/webp;charset=utf-8或image/webp(末尾空格)都会失败 -
type="image/avif"在部分 Android WebView 中可能声称支持,但实际解码崩溃 → 建议搭配兜底media="(min-width: 0px)"强制走下一组 - 只写
type="image/png"不够,PNG 有多种编码变体;若需兼容旧设备,最好用 JPEG 作为最后一个<source></source>,再紧跟<img src="fallback.jpg">
img 标签不是“备选”,而是强制存在的渲染锚点
<picture></picture>本身不渲染任何内容,它只是容器;真正触发图片请求和 DOM 渲染的是内部的<img>元素。这意味着:- 漏掉
<img>、或写成自闭合形式<img>、或没写src和alt→ 在 Safari 或 iOS 低版本中,整个区域空白,且无控制台提示 -
<img>的src是最终 fallback,但它也可以带srcset和sizes—— 这些只在所有<source></source>都不匹配时才生效,和<source></source>内部的srcset完全隔离 - 用 JS 动态插入
<source></source>可能失效:部分浏览器(尤其是旧版 Safari)不会重新触发原生格式探测逻辑,导致回退链断裂;更稳妥的做法是重建整个<picture></picture>结构
-











