SCSS变量仅在构建时生效,无法被JS运行时修改;动态样式应使用CSS自定义属性(--xxx)配合setProperty和var()实现。

SCSS 本身不能实现 CSS-in-JS 的运行时动态性,它没有“JS 控制 SCSS 变量”的能力 —— 所有 $variable 都在构建时被计算、替换、抹除,最终输出纯 CSS。所谓“共享”或“动态”,必须明确区分:是构建时导出(:export),还是运行时注入(setProperty)。
SCSS 变量无法被 JS 运行时修改
SCSS 是预处理器,不是运行时环境。你写的 $color: #333 在 webpack 构建阶段就被替换成 color: #333,DOM 中根本不存在这个变量。试图用 JS 去“改 $color”就像想给已编译的 C 程序打补丁 —— 不可能。
- 浏览器只认识 CSS,不认识
$开头的任何东西 -
document.documentElement.style.setProperty('--color', 'red')修改的是 CSS 自定义属性,和 SCSS 变量完全无关 - 即使你在 SCSS 里写
$color: var(--color),那也只是把一个字符串字面量传进去,不会建立响应式绑定
构建时共享:用 :export 把 SCSS 值导出到 JS
这是最常用、最稳妥的“共享”方式,适用于主题色、动画时长、断点等静态但需跨语言复用的常量。
- SCSS 文件中必须使用
:export块,且只能导出字符串、数字(会被转成字符串)、布尔值 - 例如:
:export { primaryColor: $primary-color; animationMs: $animation-length-ms; } - JS 中通过
import vars from './variables.scss'获取,vars.primaryColor是字符串"#fe4e5e",需手动解析或直接拼接 - 注意:如果 SCSS 中用了函数(如
darken($color, 10%)),导出的是计算后的 CSS 值(如"#d93a4a"),不是表达式
运行时动态:用 CSS 自定义属性 + var() 替代 SCSS 变量
真正能被 JS 实时修改、CSS 实时响应的,只有 CSS 自定义属性(--xxx)。SCSS 可以作为“生成器”辅助写法,但核心逻辑在 CSS 层。
立即学习“前端免费学习笔记(深入)”;
- 在
:root或目标元素上用 JS 设置:el.style.setProperty('--theme-color', 'blue') - SCSS 中可提前声明别名简化书写:
$theme-color: var(--theme-color); .btn { color: $theme-color; }—— 注意这只是语法糖,编译后仍是color: var(--theme-color) - IE11 不支持
var(),若需兼容,必须 fallback(如color: #007bff; color: var(--theme-color);) - 不要在 SCSS 中对
var()做运算(如lighten(var(--color), 10%)),Sass 编译器无法解析,会报错
为什么混合方案容易踩坑
有人尝试“SCSS 生成自定义属性 + JS 修改 + SCSS 再读取”,看似闭环,实则断裂。关键点在于:
-
var(--x)是运行时求值,而lighten($x, 10%)是构建时求值,两者不在同一时空维度 - SCSS 无法监听 CSS 自定义属性变化,
$x: var(--x)不是引用,只是字符串字面量 - Webpack 的
sass-loader不会重新编译 SCSS 文件来响应 JS 中的setProperty调用 - 真正需要运行时样式逻辑(比如根据用户偏好切换深色模式并实时调整所有组件透明度),应该直接用 CSS-in-JS 库(如
styled-components)或内联 style,而不是硬套 SCSS
最易被忽略的一点:开发者常把“SCSS 变量”和“CSS 自定义属性”当成同一种机制的不同写法,其实它们分属两个世界 —— 一个活在构建流水线里,一个活在浏览器渲染引擎中。混用前,先确认你要解决的问题到底发生在哪个阶段。


















