<picture> 标签不支持暗黑模式动态切换,仅通过 media 属性静态匹配 prefers-color-scheme;需配合 CSS 媒体查询与 source 的 media 属性实现首次加载主题适配,但切换主题后需 JS 监听 matchMedia 手动更新 <img> 的 src。

picture 标签本身不感知暗黑模式
直接用 <picture> 无法自动响应系统暗黑模式切换,它只是根据 media 属性做静态媒体查询匹配,不会监听 prefers-color-scheme 的动态变化。必须配合 CSS 媒体查询 + source 的 media 属性才能实现「首次加载时按当前主题选图」,但页面主题切换后不会重载图片。
用 media="(prefers-color-scheme: dark)" 指定暗黑图源
这是最常用、兼容性足够(Chrome 82+、Firefox 67+、Safari 14+)的做法。关键在 source 的 media 属性值要写对:
<picture> <source srcset="logo-dark.png" media="(prefers-color-scheme: dark)"> <source srcset="logo-light.png" media="(prefers-color-scheme: light)"> <img src="logo-light.png" alt="Logo"> </picture>
注意几点:
-
media值必须是完整字符串"(prefers-color-scheme: dark)",不能漏括号或空格 - 多个
source元素顺序重要:浏览器从上到下匹配第一个满足media的,所以建议把dark放前面(避免某些旧浏览器忽略prefers-color-scheme后 fallback 到 light) -
<img>是必需的 fallback,且其src应与最后一个source一致,否则无匹配时可能加载错误图片 - 不支持 Safari 13 及更早版本——它们会忽略所有
media并直接使用<img>
想支持运行时主题切换?得靠 JavaScript 补位
如果用户手动点击切换主题(比如页面上有 toggle 按钮),<picture> 不会自动更新。此时需要监听 matchMedia 并手动替换 <img> 的 src:
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
const img = document.querySelector("picture img");
const darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)");
function updateImage() {
img.src = darkModeQuery.matches ? "logo-dark.png" : "logo-light.png";
}
darkModeQuery.addEventListener("change", updateImage);
updateImage(); // 初始化
这种方案绕过了 <picture> 的语义,但能保证实时响应。适合主题由 JS 控制、而非纯系统偏好驱动的场景。
别忘了响应式 + 暗黑模式的叠加写法
实际项目中往往既要适配屏幕尺寸,又要区分明暗主题。可以把多个媒体条件用 and 连接:
<source srcset="hero-dark@2x.jpg" media="(prefers-color-scheme: dark) and (min-width: 768px)"> <source srcset="hero-light@2x.jpg" media="(prefers-color-scheme: light) and (min-width: 768px)"> <source srcset="hero-dark-mobile.jpg" media="(prefers-color-scheme: dark) and (max-width: 767px)">
注意:
- 每个
source只能有一个media,不能拆成两个属性 - 条件之间用空格分隔,
and必须小写且前后有空格 - 复杂条件容易写错,建议用浏览器 DevTools 的
Rendering面板临时模拟prefers-color-scheme测试
真正麻烦的是当设计稿要求「暗黑模式下还要保留部分亮色元素」——这时候图片本身可能就得重新出稿,而不是靠前端切换解决。


















