应同时监听系统暗黑偏好和检查根节点类名:用matchmedia('(prefers-color-scheme: dark)')监听系统切换,用document.documentelement.classlist.contains('theme-dark')确认主题类是否生效,二者协同判断当前是否真正启用暗黑主题。

在网页中监听暗黑模式切换并判断根节点是否包含特定主题类(比如 theme-dark),不能只依赖 matches() 一次性判断,因为 matches() 是静态方法,不会自动响应系统或用户主题变化。你需要结合 matchMedia 监听系统偏好 + 手动检查根节点类名,二者协同才能准确反映“当前是否处于暗黑模式且根节点已应用目标主题类”。
用 matchMedia('(prefers-color-scheme: dark)') 监听系统级暗黑切换
这是检测操作系统/浏览器是否启用暗黑模式的标准方式:
- 调用
window.matchMedia('(prefers-color-scheme: dark)')获取媒体查询对象 - 监听其
change事件,在回调中执行逻辑(如更新 UI、同步 class) -
mediaQuery.matches返回布尔值,表示当前系统是否匹配暗黑偏好
用 document.documentElement.classList.contains('theme-dark') 检查根节点实际类名
matches() 本身不适用于直接判断元素是否有某个 class——它用于 CSS 选择器匹配(例如 el.matches('.theme-dark') 功能等价于 el.classList.contains('theme-dark'),但后者更直观、性能更好):
- 推荐写法:
document.documentElement.classList.contains('theme-dark') - 若坚持用
matches():document.documentElement.matches('.theme-dark')(注意是带点的选择器) - 两者都返回布尔值,但
classList.contains更语义清晰、兼容性更好
把两者组合:只在系统暗黑且根节点含类时才认为“主题生效”
常见场景是:你通过 JS 切换主题类,同时尊重系统偏好。此时需同时满足两个条件才算“当前处于你定义的暗黑主题状态”:
- 系统偏好为暗黑(
prefers-color-scheme: dark) - 且根节点已添加
theme-dark类(说明你的主题逻辑已执行)
示例代码:
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const root = document.documentElement;
const checkThemeState = () => {
const isSystemDark = mediaQuery.matches;
const hasThemeClass = root.classList.contains('theme-dark');
if (isSystemDark && hasThemeClass) {
console.log('✅ 系统为暗黑模式,且根节点已启用 theme-dark');
} else if (isSystemDark && !hasThemeClass) {
console.log('⚠️ 系统为暗黑,但 theme-dark 类未设置 —— 可能需手动添加');
}
};
// 初始化检查
checkThemeState();
// 监听系统切换
mediaQuery.addEventListener('change', checkThemeState);
注意:避免混淆“系统偏好”和“页面实际主题”
用户可能关闭系统暗黑但手动开启页面暗黑主题(比如点击切换按钮),此时 matchMedia 为 false,但 classList.contains('theme-dark') 为 true。所以判断逻辑应按业务需求设计:
- 仅响应系统:只看
mediaQuery.matches - 仅响应手动切换:只看
classList.contains - 混合模式(推荐):以 class 为准,用
matchMedia作为初始化依据或 fallback










