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

前言

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

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-scheme和 light-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 变量实现网页系统明暗主题自动切换。

相关推荐
小万7423 小时前
God‘s Eye View 深度解析:15 路公开信号 + CesiumJS 的浏览器级 OSINT 控制台,60 帧渲染的“真实间谍卫星模拟器”
前端
IT星宿3 小时前
浏览器标签页全是一个图标:我用名字哈希生成 favicon,让每个项目都有身份标识
前端
全栈项目管理程序猿3 小时前
ArcGIS JS 基础教程(32):体元系列 - VoxelSlice 体元切片
前端·javascript
拖孩5 小时前
AI 帮我写的小程序「厨菜记」上线满月了,挣了两百块!!!
前端·后端·微信小程序
用户360055579005 小时前
Kestrel_VLLM - 13 · 为什么排除 MoE FFN Tiling 与 Tensor Core
前端
Hilaku6 小时前
AI 流式输出都用 SSE,什么时候必须换 WebSocket?
前端·javascript·程序员
奇牙coding6 小时前
Codex CLI 升级后多文件编辑静默失效:config.yaml 枚举变更排查与修复指南
java·前端·javascript·ai
小羊没烦恼!6 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
程序员老赵6 小时前
Docker 部署 Filestash:轻松搭建浏览器文件管理平台
前端·docker·开源
夏天要喝冰可乐6 小时前
给 23 万字修仙小说造个阅读站:浏览器内打包 EPUB 分页阅读 + 三主题实战
前端·产品·全栈