CSS变量可运行时动态修改并实时生效,Sass变量则在编译后消失,无法被JS读取或触发重绘,这是二者最根本的区别。

CSS变量能运行时改,Sass变量改了也没用
这是最根本的分水岭。你调用 document.documentElement.style.setProperty('--primary-color', '#8b5cf6'),所有 background-color: var(--primary-color) 的元素下一帧就变色;而 $primary-color 在 Sass 编译完就消失了,浏览器里根本查不到这个符号,JS 读不了、设不了、也触发不了重绘。
常见错误现象:
- Vue 组件里写
:style="{ '--bg': themeBg }",但底层样式用的是$bg—— 状态更新了,颜色完全不动 - 想用
getComputedStyle(document.body).getPropertyValue('--text')拿当前值,但写成$text就报错或返回空字符串 - 深色模式切换时只换
<link>标签或切 class,结果部分组件没响应,因为它们依赖的是硬编码颜色值,不是变量
作用域天然适配组件化场景
CSS 变量靠层叠规则生效:在 :root 定义是全局,在 .card 里重设 --spacing 就只影响它和子元素,无需额外传参;Sass 变量则依赖导入顺序和嵌套层级,跨文件容易冲突,且不支持“父定义、子继承”这种语义。
立即学习“前端免费学习笔记(深入)”;
使用场景:
- 微前端里各子应用想隔离主题?直接在各自容器节点上设
style="--primary-color: #ef4444"即可,不影响其他区域 - 第三方组件库(如 Element Plus)暴露了
--el-color-primary入口,你改这个变量就能覆盖,不用动它的 Sass 源码或参与构建流程 - 媒体查询中联动
prefers-color-scheme:@media (prefers-color-scheme: dark) { :root { --text: #e2e8f0; } },浏览器自动响应,Sass 做不到
不需要重新编译、不膨胀打包体积
每次换肤都生成多套 CSS bundle?那是因为你在用 Sass 变量做主题分支。CSS 变量只需要一套 CSS 文件,所有皮肤配置抽成 JSON 或 JS 对象,运行时注入即可。
性能 / 兼容性影响:
- 切换主题是毫秒级操作,没有网络请求、无样式表解析开销
- 旧项目迁移时,必须把历史代码里的
#4285f4这类硬编码值替换成var(--primary-color),否则会出现“局部不换色”的坑 -
var(--gap)不能直接参与运算,width: var(--gap) * 2整条声明会被浏览器忽略;得写成width: calc(var(--gap) * 2) - Bootstrap 5.3+ 中
--bs-primary和--bs-primary-rgb是解耦的,改一个不改另一个,焦点环、阴影就会出错
为什么不能只用 CSS 变量,还得保留 Sass?
因为有些事 CSS 变量真干不了。比如你想删掉所有表单验证图标、把栅格断点从 md: 768px 改成 md: 780px、新增一个 bg-indigo 工具类——这些都得靠 Sass 的 $enable-form-validation-icons、$grid-breakpoints、map-merge() 在编译期生成。
真正容易被忽略的地方:
- CSS 变量本质是字符串,浏览器不做类型校验;
--size: 16px和--size: 16都合法,但后者在calc()里可能出错 - 动画过渡依赖值变化:
transition: background-color 0.3s对var(--bg)有效,对 Sass 输出的硬编码值无效 - 服务端渲染(SSR)时,首次 HTML 必须带对的
:root变量值,否则首屏会闪一下再变色


















