source 的 media 属性不响应 prefers-color-scheme 切换,浏览器不会因此切换视频源;这是规范限制,video 中的 media 仅作提示,不触发重加载,须用 js 监听 matchmedia 并手动更新 src。

source 的 media 属性不响应 prefers-color-scheme 切换视频
直接用 media="(prefers-color-scheme: dark)" 写在 <source></source> 上,**浏览器不会因此切换视频源**。这不是 bug,是规范限制:<video></video> 中的 media 仅作提示,不触发重加载或回退逻辑。实测 Chrome/Firefox 均会预加载所有 <source></source>(除非显式设 preload="none"),且切换系统主题后,已播放的视频不会自动换源。
想按暗色模式切视频,得用 JS 动态替换 src
真正可控的方式是放弃依赖 media,改用 JavaScript 监听并手动更新 <video></video> 的 src 或 <source></source> 列表:
- 用
window.matchMedia("(prefers-color-scheme: dark)")获取初始状态 - 用
.addEventListener('change', handler)监听系统主题变化(注意不是onchange) - 切换时调用
video.load()并重新设置src,或清空旧<source></source>后appendChild新的 - 务必加
try/catch处理加载失败,避免静音/黑屏无提示
示例关键逻辑:
const video = document.querySelector('video');
const darkSrc = 'video-dark.mp4';
const lightSrc = 'video-light.mp4';
function updateVideoSrc() {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
video.src = isDark ? darkSrc : lightSrc;
video.load();
}
updateVideoSrc();
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateVideoSrc);
video 元素本身无法用 media 查询“换皮肤”
<video></video> 的原生控件(播放按钮、进度条等)不支持通过 @media (prefers-color-scheme: dark) 统一换色。Chromium 系浏览器虽支持部分 ::-webkit-media-controls-* 伪元素,但:
-
::-webkit-media-controls-panel等是非标准 CSS,Safari/Firefox 完全忽略 - 用
filter: invert()易导致文字反色异常,尤其在字幕区域 - 控件颜色和视频画面是分离的——深色控件 + 浅色视频画面依然突兀
更实际的做法:隐藏原生控件(controls=false),用自定义 UI + SVG 图标,再配合 :root 变量统一控制配色。
真正该用 media 属性的地方:响应式分辨率/横竖屏
<source></source> 的 media 属性最适合解决的是设备能力问题,不是主题偏好:
-
media="(min-width: 768px)"→ 加载高清版视频 -
media="(orientation: landscape)"→ 横屏时加载宽幅封面帧 -
media="(prefers-reduced-motion: reduce)"→ 为动效敏感用户加载静态 poster 替代动态预览
这些场景下,浏览器会真实跳过不匹配的 <source></source>,节省带宽。而 prefers-color-scheme 在 <video></video> 中只是“被看见”,不会被“执行”。
最易被忽略的一点:很多人以为把 media 写对了,视频就会自动响应主题切换——其实它连第一次加载都不保证按查询结果选源,更别说后续响应了。真要切换,JS 是唯一可靠路径。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











