根本原因是匹配逻辑被破坏:浏览器线性扫描<source>,遇第一个true即停;media写在<picture>上、缺括号、<source>置于<img>后、断点重叠或顺序错误(须从宽到窄),均导致仅加载兜底<img>。

为什么写了 media 却总加载同一张图
根本原因不是浏览器不支持 <picture>,而是匹配逻辑被破坏了。浏览器线性扫描 <source>,遇到第一个为 true 的就停,后面全忽略。
-
media写在<picture>标签上(如<picture media="(max-width:768px)">)→ 浏览器直接忽略该属性 -
media="(max-width: 768px)"缺少括号 → 写成media="max-width: 768px"就静默失效 -
<source>放在<img>后面 → 所有<source>被跳过,只加载<img src> - 断点重叠,比如同时存在
(min-width: 768px)和(max-width: 768px)→ 768px 宽度行为未定义,不同浏览器表现不一致 - 顺序错误:手机规则写最前 → 所有设备都命中第一条,宽屏图永远不出现
如何让 <picture> 真正按视口选图(不是缩放)
这是艺术指导(art direction)的核心——你不是让一张图拉伸适配,而是提前准备好语义不同的裁剪版本。桌面展全景、手机聚焦人脸,靠的是你导出的三张图,不是标签本身裁剪。
- 必须为每个断点准备独立裁剪图:
hero-desktop.jpg(宽幅)、hero-tablet.jpg(中景)、hero-mobile.jpg(特写) -
<source>的media值必须是合法 CSS 媒体查询,不能写media="tablet"或media="768px" - 断点要互斥且覆盖完整:
(max-width: 480px)→(min-width: 481px) and (max-width: 768px)→(min-width: 769px) -
<img>是强制兜底项,必须存在,且带src和alt;漏掉它,不匹配任何<source>时区域就是空的
WebP 优先但又要兼容老浏览器,怎么写才不翻车
关键不在“能不能用 WebP”,而在服务端响应头和 HTML 声明是否完全对齐。Chrome 显示 blocked:mime-type 就是这里出问题了。
-
<source type="image/webp">必须对应服务器返回的Content-Type: image/webp,大小写、拼写、空格全要一致 - 非法写法:
type="webp"、type="image/jpg"、type="image/jpeg "(末尾空格)都会被静默丢弃 - 推荐三层 fallback 结构:WebP
<source>→ JPEG<source>→<img src="fallback.jpg"> - 不要混用
w和x描述符在同一srcset里,否则整个srcset被忽略,回退到<img src>
为什么 sizes 总是没效果
sizes 不控制“用哪张图”,它只告诉浏览器“这张图在页面里大概占多宽”,用来辅助 srcset 中的 w 描述符做分辨率选择。而且它只能写在 <img> 上,<source> 上写的会被忽略。
立即学习“前端免费学习笔记(深入)”;
-
sizes必须写在<img>标签里,例如:<img src="..." sizes="(max-width: 768px) 100vw, 50vw"> - 如果页面中图片宽度随容器变化(比如网格布局中占 33.33%),但
sizes还写"100vw",高清屏可能误加载超大图 -
sizes值必须与实际 CSS 占位一致;调试时可临时加outline: 1px solid red看真实渲染宽度 - 用
x描述符时,sizes不是必需的;但用w描述符时,漏掉sizes会导致浏览器按默认100vw计算,小屏也可能加载大图
src,它就不动——不是不支持,是没资格动。



















