news 2026/10/6 2:41:37

在 JavaScript 中检测媒体查询:用 window.matchMedia 判断 prefers-color-scheme 暗色模式(TIL 实战笔记)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 JavaScript 中检测媒体查询:用 window.matchMedia 判断 prefers-color-scheme 暗色模式(TIL 实战笔记)
  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载

本篇指南围绕 TIL 仓库中的 javascript/check-media-queries-from-javascript.md 展开,讲解如何把原本用于 CSS 的媒体查询搬进 JavaScript 上下文,通过浏览器原生window.matchMediaAPI 读取prefers-color-scheme、prefers-reduced-motion等媒体特性的当前匹配状态。读完本文,你将掌握matchMedia的返回值结构与matches属性的用法,并能基于它实现响应式、跟随系统主题的 Light/Dark 模式切换等实战方案。

从 CSS 媒体查询说起

在 Web 开发中,媒体查询(Media Queries)通常被放在 CSS 上下文里使用:用它们控制不同屏幕宽度下的布局样式、在用户偏好减少动画时收敛动效,或者在用户偏好深色配色时切换整套颜色方案。仓库中的 css/apply-styles-based-on-dark-mode-preferences.md 就演示了如何在 CSS 侧通过prefers-color-scheme同时提供深色与浅色两套样式:

@media (prefers-color-scheme: dark) { /* dark-mode styles */ /* perhaps changing some custom properties */ } @media (prefers-color-scheme: light) { /* light-mode styles */ /* perhaps changing some custom properties */ }

该文档同时指出,prefers-color-scheme一度仍处于规范草稿(draft)状态,但当时已拥有不错的浏览器支持——这也是为什么「既要在 CSS 里写媒体查询,又希望在 JavaScript 里读到同一份匹配结果」的需求会越来越常见:很多交互逻辑(按钮状态、图标切换、内联样式、Canvas 绘制)并不适合塞进 CSS 文件里。

window.matchMedia:在 JavaScript 中查询媒体查询

媒体查询的当前值同样可以从 JavaScript 上下文检查。浏览器在window对象上暴露了matchMedia方法,它接受一个媒体查询字符串,并返回一个MediaQueryList对象,用来描述「这条媒体查询在当下环境中是否成立」。

比如,想判断用户是否偏好深色配色,可以针对(prefers-color-scheme: dark)这条查询寻找一次匹配:

> window.matchMedia('(prefers-color-scheme: dark)') MediaQueryList {media: '(prefers-color-scheme: dark)', matches: true, onchange: null}

上面这段输出直接取自原文档在浏览器控制台中的真实运行结果。可以看到matchMedia返回的MediaQueryList对象携带三个关键字段:

字段含义
media传入的媒体查询字符串,例如'(prefers-color-scheme: dark)'
matches布尔值,表示当前环境是否匹配这条媒体查询
onchange可挂载的变更回调,null表示尚未监听

media字段会被浏览器规范化(例如补全空格、合并括号),因此在控制台打印时可能与传入字符串略有差异,但语义一致。

读取匹配结果:matches 属性

MediaQueryList上的matches属性是最常被直接读取的字段。它在条件判断中可以直接当作布尔值使用,例如判断用户是否处于深色模式:

> window.matchMedia('(prefers-color-scheme: dark)')['matches'] true

原文档使用方括号形式['matches']读取属性,等价于点号写法.matches,后者在工程代码中更常见:

const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; if (prefersDark) { // 用户系统当前处于深色模式 }

注意matches是快照式的即时值:它反映调用那一刻的匹配结果。若要跟随系统设置实时变化(例如用户临时切换系统主题),还需要监听后续章节所述的变更事件。

常用可检测的媒体特性

matchMedia的查询串语法与 CSS@media完全一致,凡是 CSS 能写的媒体特性,JavaScript 侧都可以按相同写法检测。结合原文档提到的场景,常见示例包括:

// 视口宽度类:是否处于窄屏 window.matchMedia('(max-width: 600px)').matches // 减少动效偏好:用户是否要求减少非必要动画 window.matchMedia('(prefers-reduced-motion: reduce)').matches // 配色偏好:是否偏好深色/浅色配色 window.matchMedia('(prefers-color-scheme: dark)').matches window.matchMedia('(prefers-color-scheme: light)').matches

原文档点名的prefers-color-scheme是本文的核心媒体特性,其取值通常为light、dark与no-preference。值得一提的是,不少站点会在 CSS 中基于它定义颜色变量(如仓库 css/apply-styles-based-on-dark-mode-preferences.md 建议的「更换自定义属性」做法),而 JavaScript 侧同样通过它来决定逻辑分支,两者各司其职。

监听变化:跟随系统主题实时响应

MediaQueryList返回对象中的onchange字段暗示了它具备事件能力。当媒体查询的匹配状态随环境变化时,可以注册监听来获得通知——例如用户把操作系统从浅色切到深色,页面无需刷新即可感知:

const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)'); function handleChange(event) { // event.matches 即变化后的最新匹配结果 console.log('当前是否深色模式:', event.matches); } // 现代写法:addEventListener 绑定 change 事件 darkModeQuery.addEventListener('change', handleChange); // 不再需要时移除监听 darkModeQuery.removeEventListener('change', handleChange);

change事件回调收到的参数带有matches属性,与MediaQueryList.matches含义一致,可以直接用于更新页面状态(例如切换根元素上的data-theme属性、改写 CSS 变量、重绘 Canvas 等)。把「初始读取」与「变更监听」组合起来,就能覆盖「打开页面时」和「运行过程中系统偏好变化」两种时机。

实战:实现跟随系统的 Light/Dark 切换

把上面的能力组合起来,即可复刻原文档结尾所提到的经典用法——在客户端给站点接一个 Light/Dark 切换。该模式正是 Astro.build Blog 教程的「添加客户端交互」章节 所展示的例子(原文档直接引用了该教程作为实现参考),其骨架如下:

// 读取初始偏好 const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)'); let isDark = darkModeQuery.matches; // 同步 DOM:例如在根元素上加/去 dark 类,配合 CSS 中的配色变量 function applyTheme(mode) { document.documentElement.classList.toggle('dark', mode === 'dark'); } applyTheme(isDark ? 'dark' : 'light'); // 系统偏好变化时自动跟随 darkModeQuery.addEventListener('change', (event) => { isDark = event.matches; applyTheme(isDark ? 'dark' : 'light'); }); // 用户手动切换按钮 toggleButton.addEventListener('click', () => { isDark = !isDark; applyTheme(isDark ? 'dark' : 'light'); });

对应地,CSS 侧基于prefers-color-scheme或根元素上的.dark类提供两套配色。仓库中的 tailwind/use-tailwind-typography-prose-in-dark-mode.md 记录了另一种相关实践:在 Tailwind CSS 中为prose排版内容追加dark:prose-dark类,以在暗色模式下获得合理的正文默认样式——这类「类名切换」机制与上述applyTheme思路完全同源。

在 TIL 仓库中的上下文

本仓库(README.md)是一个以「Today I Learned」形式沉淀的日常技术笔记集合,主题涵盖 JavaScript、CSS、Tailwind 等多个领域。本文对应的原始笔记 javascript/check-media-queries-from-javascript.md 属于 JavaScript 分类,它与 css/apply-styles-based-on-dark-mode-preferences.md 形成互补:前者解决「在 JS 里怎么读媒体查询」,后者解决「在 CSS 里怎么写媒体查询」,配合 tailwind/use-tailwind-typography-prose-in-dark-mode.md 中的暗色模式类名实践,即可拼出完整的深浅色主题能力。

小结

  • window.matchMedia(queryString)是浏览器原生 API,返回MediaQueryList对象,其中media保存查询串、matches保存当前匹配结果、onchange可挂载回调;
  • 查询串语法与 CSS@media一致,prefers-color-scheme、prefers-reduced-motion、max-width等特性均可检测;
  • 通过addEventListener('change', ...)可以在系统偏好变化时实时更新应用状态;
  • 将「初始读取 + 变更监听 + 类名切换」组合,即可实现跟随系统偏好的 Light/Dark 模式切换,这也是 Astro 官方教程采用的交互模式。
  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载

相关推荐

上一篇:RxJS 4.x `fromEventPattern` 实战指南:用 addHandler/removeHandler 桥接任意自定义事件源
下一篇:Apollo Client 内部测试工具包 `@apollo/client/testing/internal` API 全面解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:40:28

RTX 40系显卡性能终极解锁:OptiScaler开启DLSS 5与6倍帧生成硬核指南

核心工具与性能收益评估 对于搭载RTX 40系列显卡的玩家而言,突破官方限制以获取极致游戏体验已成为可能。目前社区最成熟、最推荐的解决方案是“OptiScaler极光版”。该工具不仅实现了全中文本地化,大幅降低了配置门槛,更在底层逻辑上实现了重…

作者头像 李华
网站建设 2026/10/6 2:40:14

二叉树经典题:从实现到优化渐进讲解(提供分析与图示)

🔹博主名称:_Doubletful大家好,欢迎来到Doubletful的博客🪢博主的GitHub:Go to git_hub💠算法专栏🔷路漫漫其修远兮,吾将上下而求索文章目录前言一、相同的树题目解读递归判断代码优…

作者头像 李华
网站建设 2026/10/6 2:38:25

【2027最新精品大数据】基于大数据的北京网格化城市管理问题数据 (附源码资料)数据分析,可视化大屏_毕设选题推荐_大数据项目_数据挖掘_毕设指导_Hadoop

💖💖作者:计算机毕业设计江挽 💙💙个人简介:曾长期从事计算机专业培训教学,本人也热爱上课教学,语言擅长Java、微信小程序、Python、Golang、安卓Android等,开发项目包括…

作者头像 李华