暗黑模式切换的核心思路是提前定义好不同主题对应的CSS变量,通过切换根节点的类名或者直接修改CSS变量的值,让页面样式跟随变量变化,从而实现主题的切换效果。这种方法比单独写两套样式要高效很多,后续调整主题样式也只需要修改变量值即可。

一、定义全局CSS变量
首先需要在根选择器:root中定义亮色主题的CSS变量,这些变量会存储颜色、背景等主题相关的样式值。如果要支持暗黑模式,可以再定义一个暗黑主题的类名,在这个类名下覆盖对应的变量值。
/* 定义亮色主题变量 */
:root {
--bg-color: #ffffff;
--text-color: #333333;
--border-color: #e5e5e5;
--primary-color: #1677ff;
}
/* 暗黑主题变量覆盖 */
.dark-theme {
--bg-color: #1a1a1a;
--text-color: #e5e5e5;
--border-color: #333333;
--primary-color: #4096ff;
}
二、页面样式使用CSS变量
定义好变量之后,页面中的所有样式都不要写固定的颜色值,而是引用对应的CSS变量,这样后续切换主题时,变量值变化,所有引用该变量的样式都会自动更新。
/* 页面基础样式使用变量 */
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s; /* 添加过渡效果让切换更平滑 */
}
/* 卡片组件样式 */
.card {
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 16px;
background-color: var(--bg-color);
}
/* 按钮样式 */
.btn-primary {
background-color: var(--primary-color);
color: #ffffff;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
三、实现切换逻辑
切换逻辑可以通过JavaScript修改根节点的类名来实现,点击切换按钮时,给html或者body标签添加或移除dark-theme类名,就可以触发CSS变量的覆盖,完成主题切换。
1. HTML结构
<div class="card"> <h3>主题切换示例</h3> <p>这是一段测试文本,用于展示暗黑模式切换后的效果</p> <button class="btn-primary" id="toggleTheme">切换暗黑模式</button> </div>
2. JavaScript切换逻辑
// 获取切换按钮和根节点
const toggleBtn = document.getElementById('toggleTheme');
const rootElement = document.documentElement;
// 初始化时读取本地存储的主题偏好
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
rootElement.classList.add('dark-theme');
toggleBtn.textContent = '切换亮色模式';
}
// 点击按钮切换主题
toggleBtn.addEventListener('click', () => {
const isDark = rootElement.classList.contains('dark-theme');
if (isDark) {
// 切换到亮色模式
rootElement.classList.remove('dark-theme');
localStorage.setItem('theme', 'light');
toggleBtn.textContent = '切换暗黑模式';
} else {
// 切换到暗黑模式
rootElement.classList.add('dark-theme');
localStorage.setItem('theme', 'dark');
toggleBtn.textContent = '切换亮色模式';
}
});
四、适配系统主题偏好
除了手动切换,还可以适配用户系统的主题偏好,通过prefers-color-scheme媒体查询,在用户没有手动设置主题时,自动匹配系统的亮色或暗色模式。
/* 适配系统暗黑模式偏好,且没有手动设置主题时生效 */
@media (prefers-color-scheme: dark) {
:root:not(.light-theme) {
--bg-color: #1a1a1a;
--text-color: #e5e5e5;
--border-color: #333333;
--primary-color: #4096ff;
}
}
这里需要注意,如果用户手动切换过主题,我们会给根节点添加light-theme或者dark-theme类名,此时媒体查询的样式就不会生效,优先使用用户手动设置的主题。
五、常见问题说明
- CSS变量的兼容性:现代浏览器都支持CSS变量,如果需要兼容IE浏览器,这种方案不适用,需要改用其他主题切换方案。
- 过渡效果:给会变化的样式添加
transition属性,可以让主题切换时的样式变化更平滑,提升用户体验。 - 本地存储:把用户的主题偏好存储在
localStorage中,下次打开页面时可以自动恢复用户上次设置的主题,不需要重新选择。