因为只有css变量(--color)能在运行时被js修改并实时重绘,scss变量($color)在构建后即被替换为固定值,不进入浏览器运行时环境,故无法动态更新。

直接回答:因为只有 --color 这类 CSS 自定义属性能在运行时被 JavaScript 修改并实时触发样式重绘,$color 在构建后就彻底消失,JS 对它做任何事都等于对空气说话。
运行时改不了 $primary-color 是设计使然,不是你写错了
你在控制台执行 document.documentElement.style.setProperty('$primary-color', 'red') 会报错;在 Vue 的 <style scoped></style> 里写 $bg: v-bind(themeBg) 完全不解析;这些都不是配置问题,而是 Sass 变量压根就不进入浏览器运行时环境。
-
$primary-color只存在于.scss源文件中,经dart-sass编译后,所有出现位置都被替换成硬编码值(如#4285f4),最终 CSS 文件里搜不到$符号 - 浏览器的
CSSOM和DOM中没有$primary-color这个实体,getComputedStyle()读不到,setProperty()写不进 - 所谓“主题切换”若依赖
$color,实际是靠 JS 切换<link href="dark.css">—— 这会引发 FOUC、缓存失效、transition 中断
var(--color) 能立刻响应状态变化,但必须用对地方
Vue/React 组件里写 style="--bg: {{ theme.bg }}" 是对的,前提是你的 CSS 里用的是 var(--bg),而不是 $bg。否则变量值永远卡在编译那一刻。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- 全局变量统一放在
:root下::root { --bg: #fff; --text: #333; } - 局部覆盖直接在选择器内重定义:
.card { --bg: #f5f5f5; },其子元素自动继承新值 - Vue 的
<style scoped></style>里不能写:root { --x: y }——scoped会加属性选择器,破坏:root匹配,应移至非 scoped 样式块或index.html的<style></style> - JS 修改必须走
document.documentElement.style.setProperty('--bg', '#121212'),不要用document.body—— 否则后代元素可能拿不到
运算和类型能力差异决定怎么分工
var(--size) 不是数字,是字符串;$size 才是预处理器能算的“真变量”。两者不该互相替代,而应各司其职。
- 所有数学运算必须包在
calc()里:width: calc(var(--spacing) * 2);✅,width: var(--spacing) * 2;❌(整条声明被浏览器忽略) - 颜色明暗调整等复杂逻辑仍用 Sass:
$primary-light: lighten($primary, 10%);,然后把结果存成--primary-light供运行时使用 - 媒体查询中不能用
var()做条件判断(@media (prefers-color-scheme: dark)才是正解),但可以用它配合 JS 响应系统偏好变更 - IE 不支持
--var,若需兼容,CSS 变量只能作为增强层,主样式仍需 fallback 值:color: #333; color: var(--text);
真正容易被忽略的点是作用域污染:Sass 变量靠 @import 链传播,一个 $gap 改动可能意外影响十几个组件;而 --gap 天然受 CSS 层叠约束,父设子用、局部重写,边界清晰——这不是“更高级”,而是浏览器原生机制自带的克制。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










