网页也懂黑夜与白天:系统主题自动切换

前言

不知道大家有没有遇到过,网页会根据系统设置的外观模式,显示不同的主题样式。这是如何实现的呢?

1、核心原理:认识 prefers-color-scheme 媒体查询

CSS原生媒体特性 prefers-color-scheme 是实现主题自动切换的核心,它能检测用户操作系统(Windows、macOS、iOS、Android 等)的主题设置,返回三个可能值:

  • light:用户设置浅色主题
  • dark:用户设置深色主题
  • no-preference:用户未设置(默认按浅色处理)

能覆盖绝大多数现代设备,无需额外 JS 即可实现基础切换。

2、案例实现

2.1 定义浅色主题

先在:root中定义浅色主题的基础变量:

css 复制代码
@media(prefers-color-scheme: light) {
    :root {
        --bg-color: #ffffff;
        /* 浅色背景 */
        --text-color: #333333;
        /* 浅色文字 */
    }
}

2.2 定义深色主题

通过 @media (prefers-color-scheme: dark) 覆盖深色主题的变量:

css 复制代码
@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #121212; /* 深色背景(避免纯黑) */
    --text-color: #e5e7eb; /* 浅色文字(避免纯白) */
  }
}

2.3 页面使用

在页面样式中统一使用 CSS 变量,无需重复编写明暗逻辑:

如何监听系统模式的变化:可以监听prefers-color-scheme: dark的变化,当matches为true时,为深色模式。

js 复制代码
 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {});
js 复制代码
body {
  background-color: var(--bg-color);
  color: var(--text-color);
  font-size: 16px;
}

可以在谷歌浏览器中设置切换:

效果如下:

深色:

浅色:

3、如何简写

上面的写法稍微有点复杂,可以使用CSS 的 color-schemelight-dark()函数 ,来实现 根据系统主题(深色/浅色模式)自动切换背景和文字颜色​ 的效果。

js 复制代码
:root {
    color-scheme: light dark;
}

body {
    background-color: light-dark(#ffffff, #121212);
    color: light-dark(#333333, #e5e7eb);
    font-size: 16px;
}

告诉浏览器和操作系统,这个网页 支持浅色(light)和深色(dark)两种主题模式CSS新增的 light-dark()函数 ,允许你 在一个声明里同时为浅色模式和深色模式定义颜色

4、用户手动切换主题

虽然系统自动切换已满足大部分需求,但提供手动切换按钮能提升灵活性,核心思路是通过 JS 覆盖 CSS 变量,步骤如下:

  1. 添加切换按钮:
css 复制代码
theme-toggle">切换深色模式</button>
  1. 编写 JS 逻辑:
ini 复制代码
const themeToggle = document.getElementById('theme-toggle');
const html = document.documentElement;
// 初始化:根据系统主题设置按钮文本
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
themeToggle.textContent = isDark ? '切换浅色模式' : '切换深色模式';
// 切换主题
themeToggle.addEventListener('click', () => {
  const isCurrentlyDark = html.classList.contains('dark');
  if (isCurrentlyDark) {
    html.classList.remove('dark');
    themeToggle.textContent = '切换深色模式';
  } else {
    html.classList.add('dark');
    themeToggle.textContent = '切换浅色模式';
  }
});
  1. 补充 CSS 样式:
css 复制代码
/* 手动切换深色模式时的样式覆盖 */
:root.dark {
  --bg-color: #121212;
  --text-color: #e5e7eb;
}
/* 优先级:手动切换 > 系统主题 */
@media (prefers-color-scheme: dark) {
  :root:not(.dark) { /* 未手动切换时,遵循系统主题 */
    --bg-color: #121212;
    --text-color: #e5e7eb;
  }
}

总结

最后总结一下:系统主题自动切换的核心是通过 CSS 原生 prefers-color-scheme 媒体查询,结合 CSS 变量实现网页系统明暗主题自动切换。

相关推荐
世界哪有真情7 小时前
拿人类意识卡 AI?等于用 bug 验收正式产品
前端·人工智能·后端
Listen·Rain8 小时前
Vue3:setup详解
前端·javascript·vue.js
Patrick_Wilson9 小时前
修好 bug 只是开始:一次由监控需求反向重构日志结构的复盘
前端·监控·数据可视化
kyriewen9 小时前
面试官让我优化一个卡死的表格,我打开 Claude 五秒重写,他放下咖啡问我要不要来当组长
前端·javascript·面试
小粉粉hhh10 小时前
React(二)——dom、组件间通信、useEffect
前端·javascript·react.js
Csvn10 小时前
🤖 AI 生成前端代码的 5 个典型翻车现场及修复指南
前端
IT_陈寒11 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
索西引擎12 小时前
【React】key 属性:协调算法中的元素标识机制与最佳实践
前端·javascript·react.js
只会cv的前端攻城狮12 小时前
动态组件架构设计:从配置到事件驱动全链路解析
前端·vue.js
飞天狗12 小时前
Next.js 16 App Router 实战:服务端组件与流式渲染
前端·next.js