
直接结论:用 <source></source> 的 media 属性按视口宽度(不是设备分辨率)做条件匹配,顺序从宽到窄或从窄到宽都行,但必须覆盖所有常见断点,最后必须带 <img> 作为兜底——否则不匹配时页面空白。
为什么写了 media 却只加载一张图?
最常见原因是 <source></source> 的 media 条件没被触发,或顺序逻辑出错:
- 浏览器从上到下逐个检查
<source></source>,一旦匹配就停止,后续全部跳过;所以把(max-width: 768px)放在(min-width: 768px)后面会导致后者永远不生效 -
media值必须是合法 CSS 媒体查询,不能写成media="768px"或media="tablet" - 所有
<source></source>都没匹配时,<img>必须存在且src可访问,否则图片区域留白 - 开发工具里看 Network 面板,确认是否真发出了请求——有时缓存或 404 会伪装成“没切换”
media 写法和断点选择怎么才靠谱?
断点应基于你实际的 CSS 布局断点,而不是“主流设备尺寸”这种模糊概念。例如你用 max-width: 480px 做手机,那 <source></source> 就得对应这个值:
- 推荐按移动优先顺序写:
media="(max-width: 480px)"→media="(min-width: 481px) and (max-width: 768px)"→media="(min-width: 769px)" - 避免重叠或间隙:比如
(max-width: 768px)和(min-width: 768px)在 768px 宽度时两个都可能命中(取决于浏览器实现),建议用768px和769px明确分隔 - 桌面端常用
1200px或1440px作为大屏断点,但如果你的容器最大只到1140px,那配1200px就是浪费
sizes 不写会怎样?
sizes 是写在 <img> 标签上的属性,它告诉浏览器“这张图在页面中大概占多宽”,直接影响 srcset 中 w 描述符的选择结果:
- 不写
sizes,浏览器默认按100vw计算,小屏可能加载远超需要的大图(比如 iPhone 414px 宽却加载 1440w 图) - 如果用了
w描述符(如"photo-400w.jpg 400w, photo-800w.jpg 800w"),sizes就不是可选项,而是必填项 - 典型写法:
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw",需和实际 CSS 中该图片容器的宽度逻辑一致
容易被忽略的 MIME 类型问题
很多团队配置完 <picture></picture> 发现 .webp 或 .avif 图片在某些环境(GitHub Pages、Vercel 默认配置、Nginx 未配置)下报 Failed to load resource: the server responded with a status of 404 (),其实根本不是 404,而是服务器返回了错误的 Content-Type(比如 text/plain),导致浏览器拒绝解析。
- 检查响应头:
curl -I https://yoursite.com/photo.webp,确认Content-Type: image/webp - Vercel 用户需在
vercel.json中加"headers"规则;Nginx 需补充types { image/webp webp; image/avif avif; } - 本地测试可用
http-server加-c-1关闭缓存,排除缓存干扰











