<picture>不是<img>的简单替代,因为它本身不渲染图片,仅作容器;必须包含<source>和结尾的<img>(含src)作为兜底,否则页面空白;<source>按顺序匹配media/type条件,首个满足即生效。

为什么 <picture> 不是 <img> 的简单替代
因为 <picture> 本身不渲染图片,它只是个容器;真正显示内容的是内部的 <source> 和兜底的 <img>。如果漏掉最后那个 <img> 标签,所有浏览器都会直接空白——连错误提示都不会有。
常见错误现象:页面上图片区域完全空着,开发者工具里能看到 <picture> 结构完整,但没渲染任何图像。
- 必须以
<img>结尾,且该<img>必须有src或srcset,否则无效 -
<source>的匹配顺序从上到下,第一个满足条件的就生效,后续全部跳过 -
media属性只支持媒体查询语法(如(max-width: 768px)),不支持 JS 表达式或 class 名
怎么用 srcset + sizes 配合 <source> 实现视口适配
当你要按屏幕宽度切换不同裁剪版本的图(比如桌面端用宽图、移动端用竖构图),<source> 的 srcset 和 sizes 是关键。这里 sizes 不是图片尺寸,而是告诉浏览器“在不同视口下,这张图将占据多宽的布局空间”,从而让浏览器选最合适的 srcset 项。
示例场景:在桌面端占 80vw 宽,在移动端占 100vw,提供两套裁切图:
立即学习“前端免费学习笔记(深入)”;
<picture>
<source
media="(min-width: 769px)"
srcset="hero-desktop-1x.jpg, hero-desktop-2x.jpg 2x"
sizes="80vw"
>
<source
media="(max-width: 768px)"
srcset="hero-mobile-1x.jpg, hero-mobile-2x.jpg 2x"
sizes="100vw"
>
<img src="hero-fallback.jpg" alt="Hero">
</picture>
-
sizes值必须和 CSS 中该图片的实际布局宽度一致,否则srcset选择会偏差 - 同一
<source>中混用像素密度(2x)和宽度描述(600w)可行,但建议统一用w单位 +sizes,更可控 - Chrome DevTools 的 Network 面板里,右键图片 → “Copy → Copy response” 可验证实际加载的是哪张资源
<source> 的 type 属性怎么安全启用 WebP/AVIF
用 type="image/webp" 或 type="image/avif" 能让支持新格式的浏览器自动跳过不支持的 <source>,但前提是服务器已正确配置 MIME 类型,且图片文件本身无损转换——否则可能加载失败却回退到 <img> 的 fallback,造成格式混乱。
典型问题:本地开发时 WebP 图片显示为破损图标,但控制台无报错。
- 检查响应头:用
curl -I your-image.webp确认返回Content-Type: image/webp - 不要只依赖
type;建议搭配media使用,例如<source type="image/webp" media="(min-resolution: 1dppx)">,避免低分屏设备误加载 - AVIF 对 CPU 解码压力大,iOS Safari 16.4+ 才稳定支持,旧版 Safari 会直接跳过该
<source>,依赖下一项或最终<img>
哪些情况不该硬套 <picture>
如果只是想让一张图随容器缩放(比如 CSS 设置 max-width: 100%),用 <img srcset> 就够了。<picture> 的价值在于「内容相关的变化」:不同宽高比、不同主体裁切、不同格式优先级、艺术方向切换(art direction)。
- 纯分辨率适配(1x/2x)→ 直接用
<img srcset="..." sizes="..."> - 需要根据 DPR + 视口宽度双重判断 → 仍可用
<img>,srcset支持混合单位(如"photo-400w.jpg 400w, photo-800w.jpg 800w, photo-2x.jpg 2x") - 动态生成图片 URL(如 CMS 返回不同尺寸链接)→
<picture>难以配合 JS 拼接,此时用<img>+src动态赋值更直接
最常被忽略的一点:<picture> 内部的 <source> 不会触发懒加载,只有结尾的 <img> 支持 loading="lazy"。如果首屏外图片用了 <picture> 却忘了给 <img> 加 lazy,可能影响 LCP。



















