响应式图片中<picture>标签内<source>匹配失败会导致始终加载<img>的src,常见原因包括:<source>缺失media和type属性、media值漏写括号、服务器Content-Type与type不一致,以及Safari 16.4前版本未写<img src>时页面空白;type与media匹配按从上到下顺序,首条同时满足即终止,不可叠加推理;srcset与sizes需严格对应CSS渲染宽度,w描述符依赖sizes计算,x描述符仅适配设备像素比。

不用 picture 标签也能做响应式图片,但需要它时,漏掉 <img> 或写错 src 就会彻底不显示——这是最常发生的空白问题。
为什么写了 <source> 却始终加载 <img> 的 src?
浏览器按 <source> 顺序逐条匹配,遇到第一个同时满足 media 和/或 type 的就停,跳过后续所有规则和 <img> 的 srcset(但 <img> 本身仍必须存在)。常见失效原因:
-
<source>缺media也缺type→ 整条被忽略 -
media="(max-width: 768px)"写成media="max-width: 768px"(漏括号)→ 不匹配 - 服务器返回
image/webp文件但响应头是Content-Type: image/jpeg→ 浏览器静默跳过该<source> - 在 Safari 16.4 之前版本中,
<img>没写src→ 页面空白,无报错
type 和 media 的匹配逻辑怎么安排顺序?
type 判断格式支持度,media 判断视口条件,两者可单独使用,也可共存。但顺序决定优先级:从上到下,第一条命中即终止。因此:
- 想「格式优先」(如 AVIF → WebP → JPEG):把
type="image/avif"放最顶,再跟type="image/webp",最后用media匹配不同尺寸的 JPEG - 想「布局优先」(如横屏宽图、竖屏特写):把
media条件按从大到小排列,每条都带对应构图的图,最后<img>是手机竖版 fallback - 不要混写
media和type在同一<source>里还指望它“智能叠加”——浏览器只认是否同时满足,不推理
srcset 和 sizes 怎么配合才不白写?
<source> 和 <img> 各自的 srcset+sizes 是独立计算的,互不影响。关键点:
立即学习“前端免费学习笔记(深入)”;
-
sizes值必须与 CSS 实际渲染宽度一致(比如sizes="(max-width: 768px) 100vw, 50vw"对应max-width: 768px下图片占满视口) -
srcset中的w描述符(如"hero-400w.jpg 400w, hero-800w.jpg 800w")需配合sizes才能算出当前应加载哪张;只写x(如"a.jpg 2x")只适配 DPR,不解决尺寸切换 - 某个
<source>匹配成功,但它的srcset里没有适配当前 DPR 的项(比如只有1x图,设备是2x)→ 浏览器加载最接近的,不会跨<source>查找
WebP/AVIF fallback 为什么有时直接空白?
不是所有浏览器在 type 不匹配时都会自动走 <img> fallback。典型失效场景:
- 旧版 Safari(image/avif,但解码失败 → 页面空白
- CDN 或 Nginx 没透传
Accept请求头 → 服务器收不到image/avif声明,返回 406 或直接拒接 - 只靠
type判断,没加兜底<source media="(min-width: 0px)">→ 部分 UA 下跳过全部<source> - 最稳写法:把兼容性最强的格式(如 JPEG)放在最后一个
<source>,再紧跟<img src="fallback.jpg">,确保有确定出口
真正难调的从来不是语法,而是不同设备对 media 查询的解析差异、CDN 对 Accept 头的透传策略、以及服务器 MIME 类型配置是否严格匹配 type 属性——这些地方一错,<picture> 就会静默失效,连控制台都不报错。


















