picture 的兜底能力来自末尾的 img,但兜底只在浏览器认识 picture 元素时才生效。真正需要在发布前处理的降级场景有三类,各自的成因与处理位置不同。

第一类:浏览器不认识 picture
IE8 到 IE10 属于未知元素,picture 与其内部的 source 不会被解析成结构,页面上看不到图。处理方式是引入 HTML5 shiv,并把 picture 显式声明为块级:
<!--[if lt IE 11]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv-printshiv@3.7.3/dist/html5shiv-printshiv.min.js"></script>
<![endif]-->
picture { display: block; }
shiv 只修复元素识别,真正的资源选择交给末尾 img。IE11 认识 picture 但不支持其中的 source 选择逻辑,同样依赖 img 的 src。
第二类:WebP 资源加载失败
浏览器支持 WebP 却仍然加载失败,多数与服务端的响应头有关:Content-Type 返回 application/octet-stream 时,部分浏览器会放弃解码,直接落到下一候选或显示空白。检查方式:
curl -I https://example.com/cover.webp
# Content-Type: image/webp
CDN 只回源上传时的扩展名推断时,需要在源站或 CDN 规则里补 image/webp 映射。另外,缓存键若不区分 Accept 头,会把 WebP 内容回给不支持的客户端,这是另一类失败。
第三类:兜底地址不起作用
末尾 img 的 src 是最后的防线,两条硬性约定:
- src 必须指向真实存在的静态文件,不用占位服务、不带随机查询串;
- 不要用脚本把 src 清空后靠 source 填充,脚本失败时页面就是空白。
source 上的资源全部失效时,浏览器不会自动回落到更早的 source,只会使用 img 的 src。因此候选资源的可用性逐个验证,比多写几个候选更重要。
验证顺序
- 在不支持 WebP 的环境下访问,确认回落到 jpg;
- 用 curl 检查 WebP 的 Content-Type;
- 临时把某个 source 的地址改错,确认末图仍能显示;
- 核对 CDN 缓存配置的 Vary 是否包含 Accept。
什么时候可以不做降级
统计口径里旧版本 IE 占比为零的内后台项目,第一类处理可以省略。面向公网的项目至少保留末尾 img 的有效地址,这一条没有成本,也是所有兜底里性价比最高的部分。
