CSS自定义属性需在选择器内声明(如:root),通过var(--name)使用,依赖作用域与层叠;不可与Sass变量混用求值时机,多主题需统一管理生命周期。

怎么在CSS里声明和使用--primary-color这类变量
自定义属性(CSS Custom Properties)本质是带--前缀的变量,必须写在CSS选择器作用域内,最常用的是挂载到:root上实现全局可用。
常见错误是直接写--primary-color: #007bff;不加选择器,浏览器会忽略;或者误以为它像Sass变量一样能跨文件自动继承——其实它完全依赖CSS层叠和作用域。
-
:root里声明::root { --primary-color: #007bff; --spacing-xs: 4px; } - 组件内覆盖:
.card { --primary-color: #28a745; } - JS读写:用
getComputedStyle(document.documentElement).getPropertyValue('--primary-color')读,document.documentElement.style.setProperty('--primary-color', '#dc3545')写
为什么var(--color)有时不生效或报错
失效通常不是语法错,而是作用域或拼写问题。var()函数本身不会报错,但值为unset或initial时可能视觉上“消失”,尤其在color、background等属性中不易察觉。
典型场景:深色主题切换失败、组件库中子组件拿不到父级定义的变量、构建后CSS压缩把--前缀误删(极少见,但某些老版cssnano会)。
立即学习“前端免费学习笔记(深入)”;
- 检查是否拼错名:
var(--primay-color)→ 少了个r,返回空字符串,该属性按默认值渲染 - 确认作用域:子元素想用
:root变量,但被中间某层{ --primary-color: unset; }重置了 - 避免在
@keyframes里直接用var()做动画值(部分浏览器不支持,应提前计算好)
和预处理器变量(如Sass $color)混用要注意什么
两者根本不同:Sass变量在编译时求值,CSS自定义属性在运行时求值。混用时容易误判执行时机,导致样式“看起来没变”。
比如用Sass生成一整套--theme-* 变量,再用var()调用——这没问题;但反过来,想在Sass里#{var(--color)}取值,行不通,Sass压根不认识var()。
- 推荐模式:用Sass管理设计Token源文件,输出CSS自定义属性声明,后续全走
var() - 禁用模式:不要在
@media查询里用Sass变量控制var()的fallback值,因为var(--c, red)的red是字面量,不能是Sass插值 - 性能提示:大量
var()嵌套(如var(--color-light, var(--color-base)))对渲染性能影响微乎其微,但可读性下降,建议层级≤2
怎样让自定义属性真正支撑多主题、响应式和JS联动
关键不在“怎么写”,而在“谁来管生命周期”。放任各团队随意setProperty,很快就会出现主题残留、变量污染、媒体查询失效等问题。
真实协作中,出问题的往往不是语法,而是缺乏约定:谁负责初始化?暗色模式切换时,是重设全部--*还是只改几个核心?断网时CSS变量还存在吗?
- 初始化必须在
<head>内完成,避免FOUC;可用<style>:root{--color-mode:light}</style>硬编码兜底 - JS修改优先走统一入口函数,比如
setTheme({ primary: '#0056b3', radius: '8px' }),内部批量setProperty,而非散落各处 - 响应式慎用
@media内大量var(),更可靠的是用@media (prefers-color-scheme: dark)直接切换:root变量值
变量名一旦定稿就别轻易改,CSS里没有“重命名重构”工具,改一个--font-size-lg可能牵扯几十个组件。


















