CSS变量是唯一支持运行时动态主题切换的方案,Sass变量仅在编译期存在,JS无法读写、不触发重绘,二者本质不同、分工协作而非替代。

不推荐“弃用”Sass变量——真正该做的是停止用它承担运行时主题切换任务。Sass变量在构建后就消失,JS读不到、改不了、也触发不了重绘,拿它做主题色切换,本质是用锤子拧螺丝。
为什么 document.documentElement.style.setProperty('--color', 'red') 有效,但 $color 不行
CSS变量 --color 是浏览器真实存在的自定义属性,属于 CSSOM 的一部分;$color 只是 Sass 编译器内部的文本占位符,输出到 CSS 文件后连符号都不剩。你在 DevTools 里搜 $color,结果永远是 0 条匹配。
-
document.documentElement.style.setProperty('--color', 'red')执行后,所有color: var(--color)元素下一帧重绘 -
document.documentElement.style.setProperty('$color', 'red')直接抛InvalidPropertyError - Vue 组件中写
:style="{ '--color': themeColor }"能响应状态变化;若绑定的是 Sass 编译出的静态值(如themeColor: #007bff),颜色就卡死不动
为什么媒体查询 + prefers-color-scheme 必须配 CSS 变量
Sass 在构建阶段无法感知用户系统偏好或窗口尺寸变化,@media (prefers-color-scheme: dark) 这类规则必须在运行时生效,而只有 CSS 变量能被媒体查询动态覆盖。
- 正确写法:
@media (prefers-color-scheme: dark) { :root { --text: #eee; } } - 错误做法:用 Sass 编译两套 CSS,再靠 JS 切换
<link>标签 → 触发 FOUC、缓存失效、transition 断裂 - 深色模式下,
data-bs-theme="dark"实际依赖的是一组独立的--bs-*-dark变量,这些不是 Sass 能生成的“开关”,而是运行时注入的 DOM 属性
为什么组件库主题定制入口全是 --xxx,不是 $xxx
Element Plus 暴露 --el-color-primary,Ant Design 文档写“覆盖 --ant-primary-color”,Bootstrap 5.3+ 提供 --bs-primary —— 它们统一放弃 Sass 变量作为用户定制入口,是因为只有 CSS 变量能被第三方代码(比如你自己的 JS 主题切换逻辑)安全读写。
立即学习“前端免费学习笔记(深入)”;
- 用户改
--el-color-primary,所有var(--el-color-primary)引用自动更新,无需重编译 - 若你试图在
<style scoped></style>里写:root { --x: red },Vue 会加属性选择器(如:root[data-v-abc]),破坏匹配 → 必须移至非 scoped 块或index.html的<style></style> - 组件 JS 初始化时可能读取
getComputedStyle(el).getPropertyValue('--el-color-primary')做计算(比如阴影 rgba 值),Sass 变量对此完全不可见
真正容易被忽略的点是混合使用场景:比如用 Sass 预算 lighten($primary, 10%) 得到浅色值,再注入为 --primary-light;此时 $primary 负责静态推导,--primary-light 负责运行时分发——两者不是替代关系,而是分工协作。把它们当成同一类东西去“弃用”或“替换”,反而会让主题系统既失去编译期保障,又丢掉运行时弹性。


















