最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何利用 window.matchMedia 根据用户系统偏好自动切换网站的深色皮肤
时间:2026-07-27 09:39:53 编辑:袖梨 来源:一聚教程网
window.matchMedia 能实时响应系统深色模式切换,但必须显式绑定 change 事件监听器;直接读取 matches 属性仅获当前快照,不自动更新;需配合 CSS @media 和客户端安全执行以避免闪动与内存泄漏。
window.matchMedia 能实时响应系统深色模式切换,但必须显式绑定 change 事件监听器——不加这句,页面加载后就再也不会感知系统主题变化了。
怎么判断当前系统是深色还是亮色
直接读取 matches 属性即可,它返回布尔值:
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
注意:这个值只反映「当前快照」,不是实时状态。比如用户在页面打开后切到深色模式,isDark 不会自动变,除非你监听了 change 事件并重新读取。
- 不要用
document.body.classList.contains('dark')来反推系统偏好,那只是你上次 JS 设置的结果 - 如果浏览器不支持
prefers-color-scheme(如旧版 Safari 或 IE),window.matchMedia('(prefers-color-scheme: dark)')仍会返回一个对象,但其media属性值为'not all',可据此降级处理 - 避免同时查
light和dark两个查询,只需查一个,另一个取反即可;查两个可能因浏览器实现差异导致逻辑冲突
如何监听系统主题切换事件
必须调用 addEventListener('change', handler),且推荐在初始化时就绑定,而不是等用户点击按钮后再绑:
const media = window.matchMedia('(prefers-color-scheme: dark)');media.addEventListener('change', e => { if (e.matches) { document.documentElement.setAttribute('data-theme', 'dark'); } else { document.documentElement.setAttribute('data-theme', 'light'); }});
容易忽略的点:
- 旧版 Safari(≤13.1)不支持
addEventListener,需兼容addListener回退写法 - 如果组件卸载(如 React unmount、Vue destroy)而没移除监听器,会造成内存泄漏;务必在清理阶段调用
media.removeEventListener('change', handler) - 该事件只在系统级主题变更时触发,不会因窗口缩放、刷新或 CSSOM 修改而触发
为什么 CSS 媒体查询 + JS 监听要配合使用
CSS 的 @media (prefers-color-scheme: dark) 能让首屏直出正确样式,但无法驱动 JS 逻辑(比如图表重绘、localStorage 记录、第三方库主题切换);而 JS 的 matchMedia 可以触发这些行为,但不能替代 CSS 原生渲染性能。
- 默认把亮色变量写在
:root顶层,深色覆盖写在媒体查询内;反过来会导致深色模式下变量未定义 - 不要在组件内部重复定义同一组 CSS 变量,否则媒体查询无法穿透作用域生效
- 若同时支持手动切换和系统偏好,建议用
localStorage存储用户选择,并优先级高于系统值;否则用户点了“切亮色”,系统一变又回暗色,体验断裂
最易被绕过的细节:服务端渲染(SSR)或静态生成站点首次加载时,window 不存在,matchMedia 会报错;需要确保相关逻辑只在客户端执行,且首次渲染前就完成主题判定,否则会出现闪动(FOUC)。
相关文章
- 苹果折叠屏爆料汇总:售价超两万,比例阔折叠 07-30
- 纪念碑谷3 纪念碑谷3手游玩法详解与体验评测 07-30
- 晴空双子金卡阵容推荐 晴空双子高性价比氪金养成指南 07-30
- 大周列国志全新派系系统 07-30
- 兔小萌世界甜系小房间搭建指南 兔小萌世界高颜值甜系房间布置全流程详解 07-30
- 大周列国志全新剧本包西汉剧本包 07-30