<picture> 不是 <img> 的简单替代,因为它仅作容器,实际渲染依赖内部必需的 <img>;浏览器按序匹配 <source> 的 media/type 条件后将 srcset 交由 <img> 加载,无匹配则回退至 <img> 的 src。

为什么 <picture> 不是 <img> 的简单替代
因为 <picture> 本身不渲染图片,它只是个容器;真正加载和显示的仍是内部的 <img> 元素。浏览器会按顺序检查 <source>,匹配到第一个满足 media 或 type 条件的就停止,然后把它的 srcset(或 src)交给外层 <img> 加载。如果所有 <source> 都不匹配,或 JS 禁用、解析失败,就会回退到 <img> 的 src —— 所以 <img> 是必需的,不能省略。
常见错误是只写 <source>、漏掉 <img>,结果页面空白;或者把 <img> 放在 <picture> 外面,导致响应逻辑完全失效。
<source> 的 media 和 srcset 怎么配才不冲突
典型场景:小屏用窄图,大屏用宽图,同时支持 WebP 格式。这时要分清优先级:media 控制“在哪种视口下启用该 source”,srcset 控制“在这个视口下加载哪张分辨率的图”。两者不是互斥,而是嵌套关系。
-
media="(max-width: 768px)"表示仅当视口 ≤ 768px 时考虑这个<source> - 它的
srcset可以是"small.webp 1x, small@2x.webp 2x",让设备像素比决定加载哪份 - WebP 支持检测必须靠
type="image/webp",且要放在media之后的<source>中;否则即使浏览器支持 WebP,也会跳过它去加载下面的<img> - 多个
<source>的顺序很重要:更具体的条件(如media+type)建议放前面,避免被宽泛规则提前截断
实际项目中容易被忽略的兼容性细节
<picture> 在现代浏览器中支持良好(Chrome 38+、Firefox 38+、Safari 9.1+),但 IE 完全不支持,Edge 12–18 仅部分支持。如果需要兼容旧环境,不能只依赖 <picture> 做降级——<img> 的 src 必须是能独立工作的通用图(比如 JPEG),而不是一个占位符或 404 地址。
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
另外注意两点:
-
srcset中的宽度描述符(如800w)需配合sizes属性才能正确计算,否则浏览器可能按视口宽度而非布局宽度选图;sizes必须写在<img>上,不是<source> - 服务端不识别
<picture>,所以 SSR 渲染时若未预判客户端能力(如 UA 判断 WebP),仍需确保<img>的src是安全兜底
一个最小可用但覆盖主流需求的写法
以下代码适配移动/桌面视口 + WebP 优先 + 2x 屏幕:
<picture> <source media="(max-width: 768px)" type="image/webp" srcset="hero-sm.webp 1x, hero-sm@2x.webp 2x"> <source media="(min-width: 769px)" type="image/webp" srcset="hero-lg.webp 1x, hero-lg@2x.webp 2x"> <source media="(max-width: 768px)" srcset="hero-sm.jpg 1x, hero-sm@2x.jpg 2x"> <source media="(min-width: 769px)" srcset="hero-lg.jpg 1x, hero-lg@2x.jpg 2x"> <img src="hero-lg.jpg" alt="Hero image" width="1200" height="600"> </picture>
关键点:WebP <source> 放在同尺寸 JPEG 前面;每个 <source> 都有明确 media;<img> 的 src 与最大尺寸的 JPEG 一致,确保无 JS 或不支持时也能展示主体内容。
真正麻烦的从来不是语法,而是维护多套图资源、同步更新 srcset 中的尺寸与实际文件、以及在 CMS 或构建流程里自动化生成这些 <source> 标签。


















