<picture>降级依赖<source>顺序与<img>兜底,type须用标准MIME类型且服务器Content-Type严格匹配,浏览器自上而下匹配首个支持且可解码的<source>,<img>为强制兜底且不可省略,error事件仅作用于<img>。

<source> 本身不“降级”,它只按顺序被浏览器匹配;真正起降级作用的是整个 <picture> 结构里 <source> 的排列 + 最终的 <img> 兜底。写错 type、排错顺序、漏掉 <img>,都会导致降级静默失败。
type 属性必须写标准 MIME 类型
浏览器靠 type 值判断“这个格式我认不认识”,不是看文件后缀,也不做内容嗅探。写错就等于主动跳过。
-
type="image/avif"✅(不是"avif"或"image/avif+json") -
type="image/webp"✅(不是"webp"或"image/webp;base64") -
type="image/jpeg"✅(不是"image/jpg"—— 这是常见错误) -
type="image/png"✅(不是"image/x-png")
服务器返回的 Content-Type 必须和 type 完全一致,否则 Safari 等会静默忽略该 <source>,不报错也不往下走。
source 顺序决定实际加载结果
浏览器从上到下逐条检查,遇到第一个 type 支持 *且* 资源可解码(路径有效、格式合法、网络通)的就停,不会继续往下找。
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- 把
<source type="image/avif">放最前:Chrome 120+/Firefox 120+/Edge 120+ 可用,旧 Safari 自动跳过 - 接着
<source type="image/webp">:覆盖 iOS 14+、Android 4.0+、几乎所有桌面现代浏览器 - 最后不写
<source type="image/jpeg">,而是用<img src="logo.jpg">:JPEG 是格式兜底,不是<source>的一环
把 JPEG 写成第三个 <source> 是多余操作,还可能因服务器未配 Content-Type: image/jpeg 导致 Safari 拒绝加载。
img 标签是强制兜底,不是可选项
<picture> 不渲染自身,它只是容器;最终触发加载和显示的是匹配成功的 <source>,或——当所有 <source> 都失败时——里面的 <img>。
-
<img>必须存在,且带src和alt -
src必须指向一个静态、可直访、无需协商的路径(如/images/logo.jpg),不能带查询参数(?v=1、?format=webp) - 不要让
<img src>指向 WebP 或 AVIF:旧浏览器根本无法解码,等于没兜底 - 如果所有
<source>因 404 或跨域失败,而<img src>也 404,页面就只剩alt文本
error 事件不能监听 source,只能监听 img
<source> 元素不抛出 error 事件,也无法通过 addEventListener 捕获其加载失败。想做主动 fallback,唯一可靠入口是 <img> 的 error。
- 内联写法:
<img src="broken.jpg" onerror="this.src='/assets/placeholder.jpg'"> - JS 全局监听(推荐):
document.querySelectorAll('picture img').forEach(img => img.addEventListener('error', () => { img.src = '/fallback.jpg'; })) - 注意:如果
<img>的src本身是占位图,那它的error就不该再触发 fallback,否则会无限循环
最易被忽略的一点:所有 <source> 和 <img> 的图片必须保持相同宽高比与构图,否则格式切换时页面会视觉跳变——这不属于“降级失败”,但严重影响体验。


















