SCSS变量仅在编译期存在,编译后完全消失,无法被JS读写或响应媒体查询;CSS变量(--xxx)运行时生效,支持动态修改与主题切换,二者应职责分离:SCSS管设计系统与计算,CSS变量管运行时控制。

SCSS变量编译后就没了,别指望它在浏览器里改
SCSS变量(如 $color-primary)只存在于编译阶段,生成的 CSS 文件里根本不会出现 $ 符号。你写 :root { --color: $color-primary },结果就是无效 CSS——浏览器直接忽略这行,控制台报错 Invalid CSS after "--color:"。
真正能被 JS 读写、媒体查询响应、暗色模式切换的,只有原生 CSS 变量(--color-primary)。所以关键不是“选哪个”,而是“谁干谁的活”:
- SCSS 变量负责:设计系统源头、颜色计算(
darken($color-primary, 10%))、z-index 层级表、组件内部固定值 - CSS 变量负责:需要运行时干预的值,比如
--theme-color、--spacing-sm、--is-dark
导出 CSS 变量必须用 #{} 插值,且变量不能为 null
正确写法是::root { --color-primary: #{ $color-primary }; }。插值 #{} 是把 SCSS 变量的值“吐出来”,变成纯 CSS 字符串。
常见翻车点:
立即学习“前端免费学习笔记(深入)”;
-
Invalid null value for `#{}`:变量名拼错(比如写成$color-prmiary),或@use加载顺序不对,导致变量未定义 - 插值内容非法:传了
map、null或函数调用(如#{ get-color("primary") }),#{}只认基础类型(颜色、数字、字符串) - 忘了加
!default:在_config.scss里定义变量时没写$color-primary: #3b82f6 !default;,外部@use ... with ()覆盖就会失败
用 @use + with 统一覆盖全局配置,别再 @import
@use 是模块化管理的底线。所有变量集中放在 _config.scss,每个变量带 !default;入口文件(如 main.scss)用 @use "@/styles/config" with (...) 一次性注入定制值。
注意硬约束:
- 仅 Sass 1.23+ 支持
with,旧版本直接报Invalid CSS after "with": expected "{", was "(" -
with里只能传字面量或已定义变量,不能写表达式(calc(#{$spacing-xs} * 2)不合法) - 其他文件一律
@use "config",重复with会导致覆盖失效——Sass 不允许多次覆盖同一模块
哪些值根本不该导出为 CSS 变量
不是所有 SCSS 变量都值得变成 --xxx。导出越多,CSS 体积越大,运行时计算开销也越高(尤其大量 var(--x) 嵌套时)。
明确不推荐导出的类型:
- 纯计算中间值:如
$color-primary-dimmed: darken($color-primary, 10%),只在 SCSS 内部用,导出无意义 - 组件私有值:按钮的
$btn-border-radius、卡片的$card-shadow,外部不依赖,没必要暴露 - z-index 表:如
$z-modal: 1000,运行时改 z-index 极少见,且容易引发层叠混乱 - 字体堆栈:
$font-stack: "Inter", system-ui这种静态声明,导出反而增加 JS 干预风险
真正要导出的,得满足一个条件:这个值是否会被 JS 主动修改,或需配合媒体查询做响应式切换?如果不是,就让它安静待在 SCSS 里。


















