必须用显式声明格式降级链(avif→webp→jpg),必带标准mime类型type属性,末尾为强制兜底且src和alt不可省略;否则旧浏览器(如safari≤13.1、ie)会静默留白。

直接写 <img src="x.webp"> 在 Safari ≤13.1、IE、旧 Android WebView 中会静默留白——浏览器根本不识别 image/webp,连请求都不发,更谈不上“降级”。必须用 <picture></picture> 显式声明格式优先级,并以 <img> 为强制兜底。
为什么 <picture></picture> 是唯一可靠方案
它不依赖 JS、不发额外请求、SEO 友好,且由浏览器原生解析执行。关键不是“多备几个图”,而是让浏览器按顺序尝试首个它既支持 type 又能成功加载的资源。
-
<source></source>按格式先进性从高到低排列:image/avif→image/webp→ 最终靠<img src="fallback.jpg">承接所有不支持的环境 - IE 完全忽略
<picture></picture>,只渲染内部<img>;旧 Android WebView 若解析失败可能空白——所以<img>的src必须独立可访问、无查询参数、能直接在地址栏打开 - 写错一个字符(如
type="webp"或type="image/jpg")就会让整条<source></source>被跳过,Safari 尤其严格
type 属性必须和服务器 Content-Type 完全一致
浏览器只认标准 MIME 类型字符串,且校验响应头。Chrome 可能“侥幸”加载,但 Safari 和旧 WebView 会直接跳过。
- ✅ 正确:
type="image/avif"、type="image/webp"、type="image/jpeg"(注意不是jpg)、type="image/png" - ❌ 错误:
type="avif"、type="webp"、type="image/jpg"、type="image/webp; charset=utf-8" - 服务器返回的
Content-Type响应头必须与type完全匹配,Nginx 需配置types { image/avif avif; image/webp webp; },CDN 必须透传Accept请求头
常见静默失败场景与排查点
很多“降级没生效”不是代码写错了,而是链路断在了看不见的地方。
-
<img>的src指向logo.jpg?format=webp:旧浏览器可能触发406 Not Acceptable或返回损坏数据 -
<source></source>顺序反了,比如把image/webp放在image/avif前面 → AVIF-capable 浏览器永远用不上 AVIF - 所有格式图片宽高或裁剪比例不一致 → 切换时视觉跳变,用户感知为“闪动”或“拉伸”
- DevTools Network 面板看到状态是
blocked:mime-type或406→ 直接定位到服务端 MIME 配置或 Accept 头未透传
onerror 不是 fallback,只是最后一道防线
它只响应网络请求失败(如 404、超时),对空 src、CORS 拦截、200 占位图等完全静默。不能替代结构层面的降级设计。
- 必须内联写:
onerror="this.src='/assets/placeholder.svg'; this.onerror=null",否则 Safari/Edge 可能不触发,或陷入死循环 - 占位图优先用
data:image/svg+xml;base64,...内联 SVG,彻底规避路径风险 - 动态创建的
<img>元素,onerror必须在appendChild()前绑定,否则首次错误捕获不到 - 别指望它救活整个
<picture></picture>结构——如果<img>的src本身失效,页面就只剩alt文字
最容易被忽略的是:所有格式图片必须尺寸一致、构图一致;<img> 的 src 必须是静态可直访路径;type 和 Content-Type 必须逐字匹配。少一个条件,降级链就断在那儿。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











