不是的替代品而是容器,必须含和强制兜底的;声明条件不渲染,需带src和alt;media支持设备像素比+视口双条件切换;type实现格式fallback,顺序由兼容性差到好;sizes须匹配实际css宽度,避免高分辨率图在小屏加载。

picture 标签不是 img 的替代品,而是它的容器
直接把 <picture></picture> 当成增强版 <img> 用,十有八九会白写。它本身不渲染图片,必须配合内部的 <source></source> 和结尾的 <img> 才能生效——那个 <img> 不是备选,是**强制兜底**,缺了就啥也不显示。
常见错误现象:<picture><source srcset="a.webp"></source></picture> 页面一片空白;浏览器控制台没报错,但图片就是不加载。
-
<source></source>只负责声明“什么条件下该用哪张图”,不负责渲染 - 最后一个子节点必须是
<img>,且必须带src(哪怕只是占位)和alt -
<img>的src会被所有现代浏览器忽略(只要<source></source>匹配成功),但它仍需可访问、可解析
用 media 属性做设备像素比 + 视口宽度双条件切换
单靠 srcset + sizes 只能应对缩放/视口变化,但高保真需求常要同时区分「Retina 屏」和「普通屏」、「桌面大图」和「手机小图」。这时候 <source></source> 的 media 属性才是关键。
例如:桌面端 Retina 屏加载 2x WebP,普通屏加载 1x JPEG;移动端统一用 1x WebP(兼顾体积与清晰度):
<picture><source media="(min-width: 768px) and (-webkit-min-device-pixel-ratio: 2), (min-width: 768px) and (min-resolution: 192dpi)" srcset="hero-1920x1080@2x.webp 1920w, hero-2560x1440@2x.webp 2560w" sizes="(min-width: 1200px) 2560px, 1920px"><source media="(min-width: 768px)" srcset="hero-1920x1080.jpg 1920w, hero-2560x1440.jpg 2560w" sizes="(min-width: 1200px) 2560px, 1920px"><source media="(max-width: 767px)" srcset="hero-768x432.webp 768w, hero-1024x576.webp 1024w" sizes="100vw"> @@##@@ </source></source></source></picture>
注意:media 中的 -webkit-min-device-pixel-ratio 和 min-resolution 要并列写,因为 Safari 旧版只认前者,Firefox/Chrome 新版倾向后者。
WebP / AVIF 图片 fallback 必须靠 type + 多 source 实现
仅靠 srcset 切换不同格式的图?不行。浏览器会下载所有 srcset 里的地址(即使不匹配),浪费带宽。正确做法是每个格式单独一个 <source></source>,用 type 声明 MIME 类型,让浏览器自己跳过不支持的格式。
常见错误现象:页面在 IE 或旧版 Safari 上加载出空白,或控制台报 Failed to load resource —— 因为 type="image/webp" 不被识别,浏览器跳过该 <source></source>,但又没下一个可用的。
- 顺序很重要:把兼容性最差的格式(如 AVIF)放最前,最佳兼容的(JPEG/PNG)放最后
-
type值必须精确,image/avif不能写成avif或.avif - 不要省略
<img src="hero-fallback.jpg" alt="英雄图">的src,它就是最终 fallback 载体
<picture><source type="image/avif" srcset="photo.avif"><source type="image/webp" srcset="photo.webp"> @@##@@ </source></source></picture>
性能陷阱:sizes 属性写错会导致高分辨率图在小屏幕上加载
sizes 不是告诉浏览器“这张图有多大”,而是告诉它“**在当前视口下,这张图将占据多宽的 CSS 像素**”。如果写成固定值比如 sizes="100vw",那无论屏幕多小,浏览器都可能选中你 srcset 里最大的那个地址(比如 4000w),造成严重带宽浪费。
真实场景中,图片往往随布局响应式缩放:全宽图用 100vw,卡片内图可能只占 50vw,侧边栏缩略图甚至只有 200px。
- 用 Chrome DevTools 的 Network 面板勾选 “Disable cache” + 切换 device,观察实际加载的是哪个
srcset地址 -
sizes值应和 CSS 中该<img>的实际渲染宽度一致,可用calc()组合,比如sizes="calc(100vw - 2rem)" - 避免用
sizes="100vw"配合无约束的srcset="... 4000w",尤其在 CMS 输出的通用组件里
复杂点在于:很多团队把 <picture></picture> 封装成 React/Vue 组件,但 sizes 往往硬编码,而真实布局宽度由父级 CSS 决定——这种情况下,sizes 很容易失效,反而让高保真图成了性能拖累。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











