因为SCSS变量($color)仅在编译时存在并被替换为固定值,无法运行时修改;而CSS自定义属性(--color)可在JS中动态设置并实时重绘,是实现主题切换等动态样式的唯一通路。

SCSS 本身不能实现 CSS-in-JS 的运行时动态能力,但可以通过组合策略逼近其模块化效果:用 @import / @use 实现作用域隔离,用 :export 共享变量给 JS,用 var(--xxx) 承载真正可变的部分。关键不是“模拟”,而是分清哪些该在构建时确定、哪些必须留到运行时。
SCSS 模块化 ≠ CSS-in-JS,但能互补
很多人误以为把 SCSS 写进组件文件里就等于 CSS-in-JS —— 实际上 SCSS 编译后仍是静态 CSS,所有 $variable 都被替换成固定值,JS 完全无法修改它。真正的动态样式(比如根据 props 切换背景色)只能靠 CSS 自定义属性 + var() 实现。SCSS 在这里只是“语法糖生成器”,不是运行时引擎。
- SCSS 变量(
$color)只存在于编译阶段,输出后消失 - CSS 自定义属性(
--color)才是浏览器能实时读写的“变量” - 你可以在 SCSS 中写
color: var(--color);,但不能写lighten(var(--color), 10%)—— Sass 解析不了
用 @use 替代 @import 控制作用域
@import 是全局合并,容易污染;@use 才是现代 SCSS 的模块化入口,它让每个文件拥有独立命名空间,避免变量/混合宏冲突。
- 必须用
@use "path/to/file" as *;或@use "path/to/file" as ns;显式引入 - 所有
$variable、@mixin、@function默认私有,需加!public才能导出 - 推荐目录结构:
abstracts/_variables.scss、components/_button.scss,再统一@use组织 - 不要在
@use后直接写样式规则 —— 它只用于导入逻辑,样式应放在单独的.scss文件中
通过 :export 让 JS 读取 SCSS 常量
主题色、断点值、动画时长这些“静态但跨语言复用”的配置,适合用 :export 导出为 JS 对象,避免硬编码重复。
立即学习“前端免费学习笔记(深入)”;
- SCSS 文件中必须写成:
:export {<br> primaryColor: $primary;<br> smBreakpoint: #{$sm};<br>} - JS 中
import theme from "./variables.scss";→theme.primaryColor是字符串"#6366f1" - 导出值只能是字符串、数字、布尔值;函数调用(如
darken($primary, 10%))会被计算后导出结果,不是表达式 - 不支持嵌套对象或数组,复杂结构建议拆成多个键或改用 JSON 配置
CSS 自定义属性才是动态样式的唯一通路
如果组件需要根据 props.theme === 'dark' 切换颜色,别试图在 SCSS 里做条件判断——直接用 JS 设置 document.documentElement.style.setProperty('--bg', '#1e293b'),SCSS 里只负责消费:
- 在
:root或组件根元素上设置--bg、--text等自定义属性 - SCSS 中写:
$bg: var(--bg, #ffffff);<br>.card { background-color: $bg; } - IE11 不支持
var(),必须提供 fallback:background-color: #ffffff; background-color: var(--bg, #ffffff); - 不要在 SCSS 中对
var()做运算(如opacity(var(--alpha))),会编译失败
最容易被忽略的是边界感:SCSS 负责结构、复用和构建时推导;JS 负责状态响应和运行时注入;CSS 自定义属性是两者之间唯一的、标准的通信桥梁。混用三者时,先问一句——这个值,是在打包前就确定了,还是用户点击后才变?答案决定了它该写在哪一层。


















