自动切换网站主题:妙用prefers-color-scheme实现暗色模式检测
你是否遇到过这样的情况:晚上浏览网站时,突然弹出的白色背景让眼睛刺痛不已?或者白天打开深色模式的应用,屏幕暗得看不清内容?如今,用户对网站个性化体验的需求日益增长,而暗色模式(Dark Mode)已成为现代应用的标配功能。本文将介绍如何利用CSS的prefers-color-scheme媒体查询(媒体特性查询),帮助你的网站智能识别用户系统主题偏好,自动切换亮色/暗色模式,提升用户体验。
什么是prefers-color-scheme?
prefers-color-scheme是CSS3中引入的媒体特性(Media Feature),它允许网页检测用户操作系统或浏览器的主题偏好设置(亮色、暗色或跟随系统)。当用户在系统设置中切换主题模式时,支持该特性的浏览器会自动应用对应的CSS样式,无需手动刷新页面。
浏览器支持情况
根据caniuse-lite数据,全球超过95%的现代浏览器已支持prefers-color-scheme特性,包括Chrome 76+、Firefox 67+、Safari 12.1+、Edge 79+等主流浏览器。这意味着你可以放心地在项目中使用该特性,无需担心兼容性问题。
基础实现:CSS自动切换主题
1. 基础语法
使用prefers-color-scheme非常简单,只需在CSS中添加媒体查询块:
/* 默认样式(亮色模式) */
:root {
--bg-color: #ffffff;
--text-color: #333333;
}
/* 暗色模式样式 */
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #f5f5f5;
}
}
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
上述代码中,:root伪类定义了CSS变量(自定义属性),分别存储背景色和文本色。当用户系统设置为暗色模式时,@media (prefers-color-scheme: dark)内的样式会覆盖默认变量值,实现主题切换。transition属性确保颜色变化平滑过渡,提升用户体验。
2. 项目中的实际应用
在gh_mirrors/fr/frontend-stuff项目中,typedoc文件的核心实现:
// 代码片段来自:node_modules/typedoc/dist/lib/utils/highlighter.js
getStyles() {
const style = [":root {"];
const lightRules = [];
const darkRules = [];
// 定义亮色/暗色主题变量
style.push(` --light-code-background: ${this.highlighter.getTheme(this.light).bg};`);
style.push(` --dark-code-background: ${this.highlighter.getTheme(this.dark).bg};`);
// 应用prefers-color-scheme媒体查询
style.push("@media (prefers-color-scheme: light) { :root {");
style.push(...lightRules);
style.push("} }", "");
style.push("@media (prefers-color-scheme: dark) { :root {");
style.push(...darkRules);
style.push("} }", "");
return style.join("\n");
}
这段代码通过动态生成CSS变量和媒体查询规则,实现了代码高亮主题随系统主题自动切换的功能。
JavaScript增强:手动切换与本地存储
虽然prefers-color-scheme能自动识别系统主题,但有时用户可能希望在网站内手动切换主题(例如,系统是亮色模式,但用户希望网站显示暗色模式)。这时需要结合JavaScript实现主题切换功能,并使用localStorage保存用户偏好。
1. HTML结构
添加一个主题切换按钮:
<button id="theme-toggle">切换主题</button>
2. JavaScript实现
// 检查本地存储中的用户主题偏好,若无则使用系统偏好
const userTheme = localStorage.getItem('theme');
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
const initialTheme = userTheme || systemTheme;
// 应用初始主题
document.documentElement.setAttribute('data-theme', initialTheme);
// 主题切换按钮事件监听
document.getElementById('theme-toggle').addEventListener('click', () => {
const currentTheme = document.documentElement.getAttribute('data-theme');
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
// 更新属性和本地存储
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
});
3. 配合CSS使用
/* 默认样式 */
:root {
--bg-color: #ffffff;
--text-color: #333333;
}
/* 暗色模式样式 */
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #f5f5f5;
}
}
/* 手动切换暗色模式 */
:root[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #f5f5f5;
}
/* 手动切换亮色模式 */
:root[data-theme="light"] {
--bg-color: #ffffff;
--text-color: #333333;
}
这样,当用户手动切换主题后,localStorage会保存用户偏好,下次访问网站时将优先使用用户选择的主题。
进阶技巧:主题切换动画与过渡
为了提升用户体验,可以为主题切换添加平滑过渡效果。只需在CSS中为颜色属性添加transition:
body {
background-color: var(--bg-color);
color: var(--text-color);
/* 添加过渡效果 */
transition: background-color 0.3s ease, color 0.3s ease;
}
/* 为其他需要切换颜色的元素添加过渡 */
.header, .card, .button {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
项目应用案例
在gh_mirrors/fr/frontend-stuff项目中,多个模块使用了prefers-color-scheme特性,以下是一些关键文件和实现方式:
-
代码高亮主题切换:highlighter.js通过动态生成CSS变量和媒体查询规则,实现代码块背景色随系统主题自动切换。
-
UI组件主题适配:项目中的UI组件(如按钮、卡片等)通过CSS变量和媒体查询,实现了背景色、文本色、边框色等样式的自动适配。
-
文档站点主题:项目文档docs/jscodeshift-tutorial.md使用了类似的技术,确保代码示例和文档内容在不同主题下都有良好的可读性。
注意事项与最佳实践
-
性能优化:避免在prefers-color-scheme媒体查询中定义过多复杂样式,建议使用CSS变量集中管理颜色值,提高性能和可维护性。
-
对比度检查:确保亮色和暗色模式下的文本与背景色对比度符合WCAG标准(至少4.5:1),以保证可访问性。可以使用WebAIM对比度检查器进行检测。
-
测试覆盖:在开发过程中,务必同时测试亮色和暗色模式下的页面显示效果,确保所有元素都能正确适配。
-
尊重用户设置:当用户手动切换主题后,应优先使用用户选择的主题,而非系统主题。可以通过localStorage存储用户偏好实现这一点。
总结
prefers-color-scheme是一个简单而强大的CSS特性,它能帮助你的网站智能识别用户系统主题偏好,提供更友好的浏览体验。通过本文介绍的方法,你可以轻松实现主题自动切换、手动切换和用户偏好保存等功能。
如果你想了解更多关于prefers-color-scheme的技术细节,可以参考以下资源:
希望本文能帮助你更好地理解和应用prefers-color-scheme特性,为用户打造更加个性化、友好的网站体验!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



