css变量(--color)是浏览器运行时可读写的原生属性,真实存在于dom计算样式中;sass变量($color)是编译期消失的预处理器占位符,仅用于构建阶段计算与逻辑处理,二者生命周期、作用域及功能边界完全分离。

CSS变量和Sass变量根本不是同一类东西,选型不是“用哪个更好”,而是“谁负责哪段生命周期”——CSS变量管运行时,Sass变量管编译时。
为什么$color在JS里完全不可读
CSS变量--color是真实写入DOM计算样式的属性,浏览器能读能写;$color只是Sass编译器内部的一个文本占位符,编译完就从CSS文件里彻底消失。你执行document.documentElement.style.setProperty('$color', 'red')会直接抛InvalidPropertyError,因为浏览器根本不认识$语法。
常见错误现象:
- Vue组件中写
:style="{ '--bg': themeBg }",但themeBg实际来自$bg定义 → 绑定的是编译时的死值,状态变了颜色不动 - 想用
getComputedStyle(el).getPropertyValue('--text')取当前文字色,结果发现$text根本没有这个API
为什么var(--gap)不能直接参与运算
CSS变量本质是字符串,浏览器不解析其数值含义;Sass变量是编译期“真变量”,支持单位运算、颜色函数、条件分支等完整逻辑。
必须这样写:width: calc(var(--gap) * 2) ✅
不能这样写:width: var(--gap) * 2 ❌(整条声明被忽略)
而Sass里:$gap: 12px; width: $gap * 2; 直接输出width: 24px;
典型场景差异:
- 深色模式切换:必须用
--primary-color+ JS或媒体查询,$primary-color做不到 - 生成按钮变体:
@each循环在Sass里天然支持,在CSS变量里根本不存在迭代能力 - 主题色明度调节:
lighten($primary, 10%)是Sass内置函数,CSS里只能提前算好存成--primary-light等多个变量
为什么大型项目必须用@use而不是@import
当团队超3人、组件超200个时,变量管理会失控。@import是同步阻塞、无依赖审计的遗留语法;@use支持命名空间、循环检测、显式依赖声明,是工程底线保障。
常见踩坑点:
-
$spacing-xs: 4px定义在_button.scss里,其他文件@use后报Undefined variable→ Sass变量不自动提升,必须显式@use 'base/variables' as *或带命名空间引入 - 按用途拆分变量文件:
_colors.scss、_breakpoints.scss、_z-index.scss,避免全量注入导致样式污染 - Webpack/Vite必须配路径别名(如
@/styles),否则@use '../../../styles/mixins'写到第5层就没人敢动
兼容性与构建流程不可混谈
CSS变量零构建,现代浏览器(Chrome 49+/Firefox 31+/Safari 9.1+)全支持;IE完全不支持--var,若需兼容IE,CSS变量不可单独使用。Sass必须走编译流程,且输出兼容性取决于target配置(比如是否转译flex或rem)。
真正容易被忽略的是作用域机制差异:
- CSS变量遵循级联继承:
:root { --gap: 12px; }+.card { --gap: 24px; }→ 卡片内var(--gap)取24px,子元素默认继承 - Sass变量靠
@use顺序和文件作用域决定可见性,没有继承概念,更不能被选择器动态影响 - 想模拟局部作用域?Sass只能靠
@mixin传参,但每次调用都复制整段样式代码,体积膨胀
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











