浏览器按<source>顺序匹配首个满足type和media条件的资源,若服务器Content-Type与type不一致则静默跳过;WebP/AVIF需服务器正确配置MIME类型,且<source>应按格式先进性降序排列,<img>必须保留src和alt作为兜底。

为什么直接写 <source type="image/webp"> 有时不生效
浏览器只加载第一个 <source> 中它既支持、又满足 media 或 type 条件的资源。如果 type 声明了 image/webp,但服务器返回的响应头中 Content-Type 不是 image/webp(比如错配成 application/octet-stream),浏览器会跳过该 <source> —— 这是静默失败,无报错,最终回退到 <img>。
验证方式很简单:打开 DevTools → Network 面板,点开图片请求,看 Response Headers 里的 Content-Type 是否匹配 type 属性值。
- WebP 支持率已超 98%(Chrome/Firefox/Safari/Edge 均原生支持)
- AVIF 支持率约 85%,但需确认服务器是否正确配置 MIME 类型
- 不要省略
<img>的src和alt:它是语义必需项,也是所有不支持<picture>的旧浏览器唯一能加载的入口
怎样组织 <source> 顺序才能让 WebP/AVIF 真正被选用
浏览器按 <source> 出现顺序依次检查,遇到第一个“条件全满足”的就停,不再往后看。所以要把格式最新、体积最优的放前面,兼容性最广的放后面。
错误写法:<source srcset="photo.jpg" type="image/jpeg"> 写在第一个 → 所有浏览器都满足 JPEG 支持,直接用它,WebP/AVIF 永远不会被选中。
立即学习“前端免费学习笔记(深入)”;
- 正确顺序:AVIF → WebP → JPEG/PNG(按格式先进性降序)
- 每个
<source>可同时带type和media,比如小屏设备优先用 WebP,桌面再试 AVIF - 不需要为每种格式都写
media;若想全尺寸统一格式适配,可省略media,只靠type分流
type 属性和服务器 MIME 类型必须严格一致
type="image/avif" 不等于 “只要文件后缀是 .avif 就行”。如果 Nginx/Apache 没配置 AVIF 的 MIME 映射,或 CDN 缓存了错误的 Content-Type,浏览器会认为该资源不可用。
常见修复方式:
- Nginx:在
mime.types或 server 块中加types { image/avif avif; } - Apache:在
.htaccess或 conf 中加AddType image/avif .avif - Vercel/Netlify:通常默认支持,但需确认构建后文件未被转码或重命名
漏掉这步,<picture> 就退化成纯 <img>,所有多格式努力白费。
要不要给每个 <source> 都配 srcset 和 sizes
不需要。如果你只关心“格式切换”,不涉及宽度断点或 DPR 适配,那么每个 <source> 只用 srcset 指向单个文件即可(甚至可用 src,但 srcset 更规范)。
例如这个极简多格式结构完全合法且有效:
<picture> <source srcset="photo.avif" type="image/avif"> <source srcset="photo.webp" type="image/webp"> <img src="photo.jpg" alt="描述"> </picture>
但注意:一旦你加了 media,就必须确保每个 <source> 的 srcset 提供的是该断点下合理的图源(比如小屏不用 4K AVIF),否则浪费带宽。
真正容易被忽略的是——<img> 标签自己也可以带 srcset 和 sizes,用于兜底场景下的 DPR 适配。别只让它干巴巴地加载一张 1x JPG。



















