<source>的media属性必须是合法CSS媒体查询(如(max-width: 767px)),写在<picture>内按顺序匹配首个为true的条件并加载其srcset,其余跳过;<img>必须作为最后子元素提供src和alt兜底。

picture 里用 source 的 media 属性做响应式图片切换
直接说结论:<source> 的 media 属性必须是有效的媒体查询字符串,且只在 <picture> 内部生效——它不会触发 CSS 媒体查询的级联行为,也不影响其他元素。
常见错误是把 media 写成 min-width: 480px 却漏掉括号,或者混用 srcset 和 src 导致 fallback 失效。
-
media值必须是完整、可解析的媒体查询,比如(max-width: 767px),不能写max-width: 767px(缺括号) - 多个
<source>按顺序匹配,浏览器从上到下找第一个满足media条件的,匹配后就跳过后续<source> -
<img>必须作为<picture>的最后一个子元素,它是兜底方案,不参与media匹配,但必须有src和alt
media 和 srcset 如何配合使用
media 控制“什么时候用这张图”,srcset 控制“这张图用哪个分辨率版本”,两者职责不同,常一起用。
典型场景:小屏用 1x/2x 图片,大屏换另一组图;或横屏竖屏加载不同构图的图片。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
- 横向设备(
orientation: landscape)下加载宽幅图:<source media="(orientation: landscape)" srcset="wide.jpg 1x, wide@2x.jpg 2x"> - 高 DPR 设备优先加载高清图,但仅限于某宽度区间:
<source media="(max-width: 600px) and (-webkit-min-device-pixel-ratio: 2)" srcset="small@2x.jpg"> - 注意:IE 不支持
srcset和media,需确保<img src="fallback.jpg">可用
为什么 picture + source 的 media 不生效
最常踩的坑不是语法错,而是逻辑冲突或加载时机问题。
- 页面已渲染完成后再动态插入
<picture>,部分浏览器(尤其是旧版 Safari)可能忽略media并直接加载<img>的src -
media查询结果依赖 viewport 设置,如果页面没设<meta name="viewport" content="width=device-width">,(max-width: 480px)在移动端可能永远不匹配 - 使用
display: none隐藏<picture>时,Chrome 会暂停所有<source>加载,包括已匹配的——这不是 bug,是规范行为
用 JavaScript 动态控制 source 的 media 值要小心什么
可以改 source.media,但别指望它立刻触发重选源——浏览器只在元素插入 DOM 或窗口 resize 时重新评估,不会监听属性变化。
- 修改
media后,手动调用pictureElement.querySelector("img").src = ""强制重载(不推荐,破坏缓存) - 更稳妥的做法是重建整个
<picture>结构,或用matchMedia()监听并显式切换<img>的src - 服务端渲染时,
media是静态字符串,无法根据用户 UA 或网络类型(如prefers-reduced-motion)自动适配,得靠 JS 补充
真正麻烦的是多条件嵌套和浏览器兼容性差异,比如 (hover: hover) and (pointer: fine) 在 iOS 上始终为 false,这类特性几乎没法靠 media 可靠落地。


















