CSS 变量 var 实现主题切换
FreeGuideOnline
最新
2026-07-06
切换暗黑模式
```javascript
const toggleBtn = document.getElementById('theme-toggle');
const htmlElement = document.documentElement;
// 检查本地存储,保持用户偏好
const currentTheme = localStorage.getItem('theme');
if (currentTheme === 'dark') {
htmlElement.setAttribute('data-theme', 'dark');
}
toggleBtn.addEventListener('click', () => {
if (htmlElement.hasAttribute('data-theme')) {
htmlElement.removeAttribute('data-theme');
localStorage.setItem('theme', 'light');
} else {
htmlElement.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
}
});
这样,点击按钮会全局切换主题,所有使用 var() 的地方都会立即更新。
进阶技巧一:跟随系统主题自动切换
使用 prefers-color-scheme 媒体查询,无需 JS 即可让页面跟随操作系统主题。
@media (prefers-color-scheme: dark) {
:root {
--bg-body: #0f172a;
--bg-card: #1e293b;
--text-primary: #f1f5f9;
/* 其他暗色变量 */
}
}
如果同时希望保留手动切换能力,可以在 JS 中监听系统变化,并结合用户选择。更稳健的实践是检测用户是否已明确选择,若未选择则采用系统偏好。
进阶技巧二:主题变量继承与作用域
CSS 变量遵循层叠规则。你可以在任意元素上重新定义变量,仅在局部生效。例如,为特定组件设置独立主题:
.special-card {
--bg-card: #fef3c7;
--text-primary: #92400e;
}
这样 .special-card 内部使用的 var(--bg-card) 将取自局部定义,而不影响全局变量。
进阶技巧三:使用 HSL 和透明度变量
为提高灵活性,可以将颜色定义为 HSL 值,并单独控制透明度。例如:
:root {
--color-primary-h: 221;
--color-primary-s: 83%;
--color-primary-l: 53%;
--color-primary: hsl(var(--color-primary-h), var(--color-primary-s), var(--color-primary-l));
--color-primary-alpha: hsla(var(--color-primary-h), var(--color-primary-s), var(--color-primary-l), 0.2);
}
[data-theme="dark"] {
--color-primary-l: 65%; /* 仅调整亮度 */
}
这样在不同主题下只需调整 HSL 分量,仍能保持色相与饱和度一致。
完整示例代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 变量主题切换</title>
<style>
:root {
--bg-body: #ffffff;
--text-primary: #111827;
--bg-card: #f3f4f6;
--border-color: #e5e7eb;
}
[data-theme="dark"] {
--bg-body: #111827;
--text-primary: #f9fafb;
--bg-card: #1f2937;
--border-color: #374151;
}
body {
background-color: var(--bg-body);
color: var(--text-primary);
font-family: system-ui;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 2rem;
transition: background-color 0.3s, color 0.3s;
}
.card {
background-color: var(--bg-card);
border: 1px solid var(--border-color);
padding: 1.5rem;
border-radius: 0.5rem;
width: 280px;
margin-top: 1rem;
transition: background-color 0.3s;
}
button {
margin-top: 1.5rem;
padding: 0.6rem 1.2rem;
border: none;
border-radius: 0.375rem;
background-color: #3b82f6;
color: white;
cursor: pointer;
font-size: 1rem;
}
button:hover {
background-color: #2563eb;
}
</style>
</head>
<body>
<h1>CSS 变量主题切换演示</h1>
<div class="card">
<p>这是一个卡片组件。</p>
<p>背景与文字会随主题变化。</p>
</div>
<button id="theme-toggle">切换主题</button>
<script>
const btn = document.getElementById('theme-toggle');
const html = document.documentElement;
const saved = localStorage.getItem('theme');
if (saved === 'dark') html.setAttribute('data-theme', 'dark');
btn.addEventListener('click', () => {
if (html.hasAttribute('data-theme')) {
html.removeAttribute('data-theme');
localStorage.setItem('theme', 'light');
} else {
html.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
}
});
</script>
</body>
</html>