必须用 @each 遍历 map 生成 :root 中的 css 变量,因 map-get() 不允许在全局作用域调用;键名须小写加短横线,避免空格、点号等非法字符,并配合 !default 防覆盖。

直接用 @each 遍历 Map,拼出 --color-primary 这类变量名,再赋值——别手写、别硬编码、别漏 !default。
为什么不能直接 color: map-get($colors, primary) 在顶层写?
Sass 编译器不允许在全局作用域(即不在 @mixin、@function 或选择器内部)调用 map-get()。它会报错:Undefined operation "map-get" 或类似提示。Sass 的 map 函数必须在有作用域上下文的地方执行。
常见错误写法:
$colors: ("primary": #007bff);
color: map-get($colors, primary); // ❌ 报错:not allowed at top level
正确做法是把取值逻辑包进 @mixin 或塞进 :root 选择器里。
如何安全生成 :root 中的 CSS 变量?
核心是用 @each $name, $color in $colors 动态插值,确保键名与变量名一一对应,且避免引号污染。
-
--color-#{$name}会生成--color-primary,不是--color-"primary"—— 所以 Map 的 key 写"primary"没问题,但插值时不会带引号 - 务必加
!default,否则多次@import同一个文件会导致变量被覆盖或冲突 - 不要在 Map 值里用带单位的颜色函数(如
lighten(#007bff, 10%)),因为 CSS 变量不支持运行时计算;明暗变体应提前算好再存进 Map
示例:
$colors: (
"primary": #007bff,
"surface": #ffffff,
"error": #dc3545
);
:root {
@each $name, $color in $colors {
--color-#{$name}: #{$color};
}
}
Map 键名写错会导致变量名崩掉
键名不是“随便起”,它会直接变成 CSS 变量后缀。一旦含空格、大写、点号或连字符,生成的变量就非法或不可用。
-
"primary-text"→--color-primary-text✅ 合法(短横线允许) -
"primary text"→--color-primary text❌ 空格导致语法错误 -
"Primary"→--color-Primary✅ 合法但不推荐(CSS 变量习惯小写) -
"primary.text"→--color-primary.text❌ 点号会被解析为类名分隔符,浏览器拒绝解析
建议统一用小写 + 短横线,和 HTML data-theme、BEM 类名风格对齐。
多主题切换时,:root[data-theme="dark"] 怎么写?
不能只靠一套 $colors,得定义 $themes Map,外层遍历主题,内层遍历颜色键值对。
结构示例:
$themes: (
"light": (
"primary": #007bff,
"surface": #ffffff
),
"dark": (
"primary": #0d6efd,
"surface": #121212
)
);
@each $theme-name, $theme-map in $themes {
:root[data-theme="#{$theme-name}"] {
@each $color-name, $color-value in $theme-map {
--color-#{$color-name}: #{$color-value};
}
}
}
注意:data-theme 的值必须和 Map key 完全一致(包括引号类型、大小写),JS 切换时也得严格匹配,否则样式不会生效。
最容易被忽略的是:生成的 CSS 变量名是否真被用了——检查 DevTools 的 computed 样式里 var(--color-primary) 是否解析成功,而不是只看 :root 里有没有那行声明。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











