- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
本篇指南围绕 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
相关推荐
基于 prefers-color-scheme 媒体查询实现深色模式适配 —— til 仓库 CSS 实战指南
基于 prefers color scheme 媒体查询实现深色模式适配 —— til 仓库 CSS 实战指南 现代操作系统与浏览器普遍允许用户声明自己更偏好深
文档教程知识库自动切换网站主题:妙用prefers-color-scheme实现暗色模式检测
自动切换网站主题:妙用prefers color scheme实现暗色模式检测 你是否遇到过这样的情况:晚上浏览网站时,突然弹出的白色背景让眼睛刺痛不已?或者白
前端文档Enzyme测试组件黑暗模式:prefers-color-scheme测试
Enzyme测试组件黑暗模式:prefers color scheme测试 在现代Web应用开发中,黑暗模式已成为用户体验的重要组成部分。通过CSS的 pref
测试前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考