CSS自定义属性以--开头在:root声明实现主题色管理,通过var()引用,支持动态切换和JS读写,但需注意作用域、大小写敏感及fallback机制。

如何在 CSS 中定义和使用自定义属性(CSS 变量)管理主题色
直接在 :root 里声明颜色变量,所有后代元素都能通过 var(--primary-color) 引用。它不是“运行时变量”,而是级联生效的静态声明,修改后浏览器自动重绘。
- 必须用双破折号开头,如
--primary-color,不能写成primary-color或$primary -
作用域基于选择器:写在
:root是全局;写在.dark-theme内就只对该类及其子元素生效 - 不支持 IE,Edge 15+ 和所有现代浏览器都 OK;若需兼容 IE,得配 postcss-css-variables 插件做编译降级
- 值可以是任意合法 CSS 值:
--gap: 1rem、--shadow: 0 2px 4px rgba(0,0,0,0.1)都行
:root {
--primary-color: #4a6fa5;
--text-color: #333;
--bg-color: #fff;
--border-color: #e0e0e0;
}如何动态切换主题色(比如亮色/暗色模式)
靠 class 切换 + 层叠覆盖是最轻量、最可控的方式。不要试图用 JS 批量改几十个 style.setProperty,维护成本高且易出错。
- 把暗色变量写在
.dark类下,和:root同级或嵌套均可,但确保选择器权重不弱于原声明 - 用
prefers-color-scheme媒体查询可自动响应系统偏好,但手动开关仍需靠 class 控制 - 切换时只需
document.documentElement.classList.toggle('dark'),无需操作每个变量 - 注意:CSS 自定义属性不触发重排(reflow),只触发重绘(repaint),性能友好
:root {
--primary-color: #4a6fa5;
--bg-color: #fff;
}
.dark {
--primary-color: #6b8cbc;
--bg-color: #1e1e1e;
}
body {
background-color: var(--bg-color);
color: var(--text-color, #333); / 提供 fallback /
}
为什么 var(--color) 有时不生效?常见失效场景
不是语法写错了,大概率是作用域、拼写或 fallback 导致的“静默失败”。浏览器不会报错,只会回退到默认值或继承值。
- 变量名大小写敏感:
--PrimaryColor和--primarycolor是两个不同变量 - 作用域没覆盖到:在
.card里定义了--text,但p标签不在 .card 内,就读不到 - 忘记写 fallback:
color: var(--text-color)如果变量未定义,会变成color: inherit,看起来像“没变” - 在
@keyframes或伪元素::before中使用时,确保父元素已声明该变量(伪元素继承父级自定义属性)
如何用 JavaScript 读写 CSS 变量实现运行时主题更新
JS 操作的是计算后的样式值,所以读取要用 getComputedStyle,写入用 style.setProperty。注意:只能改元素自身的 style,影响范围取决于你操作的对象。
立即学习“前端免费学习笔记(深入)”;
- 读取全局变量:
getComputedStyle(document.documentElement).getPropertyValue('--primary-color') - 写入到根元素(全局生效):
document.documentElement.style.setProperty('--primary-color', '#ff6b6b') - 写入到某个组件(局部生效):
cardEl.style.setProperty('--accent', 'gold') - 批量更新多个变量时,建议封装函数,避免重复调用
setProperty影响性能
function setTheme(theme) {
const root = document.documentElement;
root.style.setProperty('--primary-color', theme.primary);
root.style.setProperty('--bg-color', theme.bg);
root.style.setProperty('--text-color', theme.text);
}CSS 变量真正难的不是声明,而是设计变量命名层级和 fallback 策略——比如 --color-brand-primary 和 --color-ui-border 要不要拆开,var(--color-text, #333) 的 fallback 是写死值还是另一个变量,这些决定了后期换肤时改几处。










