img的src必须指向高兼容性兜底图(如JPG/PNG),srcset提供响应式/高DPR候选资源,浏览器自动择优加载并失败回退至src;WebP/AVIF降级须用<picture>显式声明type优先级,<img src>为最终必需兜底。

img 的 src 和 srcset 怎么配合 fallback
浏览器加载图片失败时,<img> 默认只显示一个空白框或占位符(取决于 UA 样式),没有内置重试或降级机制。所谓“降级逻辑”,本质是提前准备多套资源,并交由浏览器按规则选择——不是 JS 捕获错误后再替换 src(那已属兜底,非真正降级)。
核心靠两个属性协同:src 提供基础兼容性兜底,srcset + sizes 提供响应式/高 DPR 优先选项。浏览器会根据设备像素比、视口宽度、网络条件(如果启用了 fetchpriority 或 loading)自主择优加载,失败时自动回退到 src。
-
src必须存在,且应指向一个体积小、格式兼容性极广的图(如.jpg或.png),不能留空或填占位 URL -
srcset中的每个候选值需带宽度描述符(w)或像素密度描述符(x),例如"photo@2x.jpg 2x, photo@1x.jpg 1x" - 若用
w描述符,必须同时提供sizes属性,否则浏览器无法计算对应宽度,可能忽略整个srcset
当 WebP/AVIF 不支持时怎么 fallback 到 JPG/PNG
现代格式(WebP、AVIF)压缩率高,但旧版 Safari、IE 完全不支持。不能只写 src="photo.avif",否则这些浏览器直接 blank。正确做法是用 <picture> 显式声明格式优先级。
浏览器从上到下解析 <source>,遇到第一个格式支持且媒体查询匹配的就加载,不再继续;都不匹配则退化到内部 <img> 的 src。
立即学习“前端免费学习笔记(深入)”;
<picture> <source type="image/avif" srcset="photo.avif"> <source type="image/webp" srcset="photo.webp"> <img src="photo.jpg" alt="描述文字"> </picture>
-
type属性必须精确匹配 MIME 类型,image/avif不能写成avif或.avif - 所有
srcset值必须真实可访问,否则该<source>条目被跳过(不会报错,但也不加载) -
<img>的alt是必需的,且仅对它生效;<source>不支持alt
图片加载失败后用 JS 补救是否可靠
监听 img.onerror 然后换 src 是常见做法,但它有硬伤:只触发一次,且不区分“404”“CORS 拒绝”“MIME 错误”等不同失败原因;更关键的是,它发生在浏览器渲染流程之后,用户会先看到空白或破损图标,体验割裂。
- 不要在
onerror里设置相同的 URL,否则无限循环(必须确保备用地址与原地址不同) - 避免在
onerror中发起新请求前检查img.naturalWidth === 0,因为某些情况下(如 CORS)该值可能仍为 0 即使加载完成 - 若必须用 JS 补救,建议结合
loading="lazy"延迟非首屏图,并在onerror后加img.removeAttribute('srcset')防止后续重复尝试
CDN 或代理层做格式协商是否更彻底
服务端根据 Accept 请求头返回不同格式(如客户端支持 AVIF 就返回 AVIF,否则返回 WebP,再否则返回 JPG),前端只需写一个 URL,无需 <picture>。这确实更干净,但依赖基础设施支持,且对缓存策略要求极高。
- CDN 必须能解析并转发
Accept头,且对同一 URL 的不同格式响应做独立缓存(否则 A 用户拿到 AVIF,B 用户用旧浏览器却命中了 AVIF 缓存,直接失败) - 部分 CDN(如 Cloudflare Image Resizing)支持通过 URL 参数指定格式(
?format=avif),但此时仍是客户端决策,未脱离<picture>逻辑 - 纯静态托管(如 GitHub Pages、S3)无法做 Accept 协商,只能靠前端降级
真正容易被忽略的是:无论用 <picture> 还是服务端协商,都必须保证所有 fallback 路径的图片语义一致(尺寸比例、关键内容区域),否则降级后构图突变,比加载失败还糟。



















