<picture>必须包含<img>作为fallback,否则不渲染;<source>按顺序匹配media和type,任一缺失则跳过;sizes描述图片预计渲染宽度,非目标宽度;WebP/AVIF回退需将JPEG放最后并设<img src>确保出口。

media 在某些 Android WebView 里被解析成 false,或者 type="image/avif" 看似匹配了,但服务器返回的是 image/jpeg,浏览器就静默跳过整条 <source>。
下面分几个实操中高频踩坑的点来说。
为什么加了 <source> 却始终加载 <img src>?
浏览器按顺序逐条匹配 <source>,遇到第一条同时满足 media 和 type 的就停,后续全忽略。但如果你漏写了 media 或 type,这条 <source> 直接被跳过,不报错也不警告。
-
media必须是合法媒体查询,比如(min-width: 768px);写成min-width: 768px(缺括号)或空字符串,该<source>就失效 -
type必须和响应头的 MIME 类型严格一致:服务器返回image/webp,你就得写type="image/webp";写成type="image/webp;"(多一个分号)也会失败 - Chrome 120+ 对
min-resolution: 2dpi这类写法更敏感,建议统一用2dppx - 检查网络面板:如果看到
net::ERR_ABORTED或状态码406,大概率是 Nginx 没透传Accept请求头,导致 WebP/AVIF 被拒
srcset + sizes 怎么配才不浪费带宽?
sizes 不是“我要这张图多大”,而是告诉浏览器:“这张图在当前布局下,**预计会渲染成多宽**”。浏览器靠这个 + srcset 里的 w 描述符,算出最接近的资源。
- 如果 CSS 把图片限制在
max-width: 600px,但sizes写成"100vw",浏览器可能选中hero-1920w.jpg,哪怕实际只显示 300px 宽 - 每个
<source>的sizes只影响它自己的srcset计算,和别的<source>或<img>无关 -
<img>的srcset+sizes只在所有<source>都不匹配时才生效,它是 fallback 场景下的增强,不是主逻辑
WebP/AVIF 回退为什么有时空白?
不是所有“不支持 WebP”的浏览器都会乖乖走 <img src>。旧版 Safari、某些 Android WebView 会在 type 不匹配时直接留白,而不是降级。
- 最稳结构:把兼容性最强的格式(如 JPEG)放在最后一个
<source>,再紧跟<img src="fallback.jpg">,确保有确定出口 - 避免只靠
type判断:有些 WebView 声称支持image/avif,但解码失败;可加兜底media="(min-width: 0px)"强制命中 -
<picture>是纯客户端机制,服务端Accept头协商不参与决策——别指望后端根据请求头动态返回不同格式
<picture> 必须包含 <img> 吗?
必须。没有 <img>,<picture> 就是空容器:不渲染、不触发任何图片请求,连 alt 文本都不会出现。
立即学习“前端免费学习笔记(深入)”;
-
<img>的src是 fallback,不是可选配置;即使你 100% 确信所有用户都支持 WebP,也得写 -
<img>的alt是唯一能被读屏器识别的文本,<source>上设alt无效 - 不支持
<picture>的老浏览器(如 IE)会直接忽略整个标签,只渲染<img>,所以它既是降级,也是兼容层
media 查询在不同设备上的解析差异——比如某些折叠屏在横竖屏切换时,(orientation: landscape) 可能延迟触发,或者媒体查询被 CSS container queries 覆盖。上线前务必在真机上测横屏/竖屏/折叠/高 DPR 多种组合,不能只靠 Chrome DevTools 模拟。



















