CSS变量必须在:root中定义,SCSS仅用于生成CSS;深色模式应通过@media(prefers-color-scheme:dark)覆盖:root变量值,而非JS或class切换;所有硬编码颜色须替换为var(--x)并统一管理。

直接在:root里定义变量,别绕弯
SCSS 本身不能“把十六进制转成 CSS 变量”,它编译后就没了。真正起作用的是你在 :root 中写的 CSS 自定义属性。比如你写:
:root { --color-primary: #4a6fa5; }
这才是浏览器能读取、能被 var(--color-primary) 引用的变量。SCSS 只是帮你组织和生成这段 CSS 的工具。
常见错误现象:Uncaught TypeError: Cannot read property '--color-primary' of undefined——这不是 SCSS 问题,是 JS 没等 CSS 加载完就读取了 getComputedStyle(document.documentElement).getPropertyValue();或者压根没在 :root 里定义该变量。
- 所有颜色值必须统一收进
:root,不能分散在各组件里写:root .btn { color: #4a6fa5; } - 变量名带语义,如
--text-primary,而不是--color-1 - 十六进制优先用小写、不带缩写(
#fff→#ffffff),避免构建工具自动转换出错
用@media (prefers-color-scheme: dark)覆盖变量值
系统级深色模式切换靠这个媒体查询,不是靠 JS 或 class 切换。它在构建时保留,在运行时生效:
立即学习“前端免费学习笔记(深入)”;
:root { --bg-color: #f8fafc; --text-primary: #0f172a; }@media (prefers-color-scheme: dark) { :root { --bg-color: #0f172a; --text-primary: #f1f5f9; } }
注意:Sass 编译器看不到用户系统偏好,@if $theme == 'dark' 这类写法对 prefers-color-scheme 无效——那是编译时逻辑,而媒体查询是运行时行为。
- 不要在
@media里重写整套选择器(如.card { background: #1e293b; }),只改变量值 - 如果项目需兼容旧浏览器(如 IE),得 fallback 到
html.darkclass 方案,但此时所有引用处必须用var(--x),不能硬编码 - PostCSS 或某些 CSS-in-JS 工具可能提前移除未匹配的媒体查询,导致深色变量不生效,需检查构建产物中是否保留了
@media (prefers-color-scheme: dark)
SCSS 可以辅助生成变量,但不能替代 CSS 变量作用域
你可以用 SCSS 变量做“源数据”,再输出为 CSS 变量:
$color-primary: #4a6fa5;$color-primary-dark: #60a5fa;:root { --color-primary: #{$color-primary}; }@media (prefers-color-scheme: dark) { :root { --color-primary: #{$color-primary-dark}; } }
但这里 $color-primary 只是编译期占位符,最终生效的仍是 --color-primary 这个 CSS 变量。Sass 不会、也不能让浏览器“感知”这个变量在 JS 里动态改。
- 别在 Sass 中用
#{var(--color-primary)}—— 语法错误,var()只能在 CSS 值里用,不能当 Sass 表达式 - 若已用
@use,Sass 模块默认不导出变量;要用@forward "variables" as var-*;或改回@import(旧语法)才能全局访问 - 深色模式下慎用
lighten($color, 10%)直接算值——它在浅色基底上有效,在深色基底上常导致灰紫失真;更稳妥的是预设两套值,或用color.contrast-color($color)返回黑白
硬编码色值是主题失效的根源
只要 CSS 文件里还存在 color: #333、background: white 这类写法,深色模式就必然漏切。不是“加个媒体查询”就能解决,而是必须全线替换为 var(--text-primary)。
已有项目改造时,自动化工具(如 chroma-js + AST 解析)比手动搜替换可靠得多——它能识别 rgb(51, 51, 51) 和 #333 是同一色,并映射到对应变量。
- 命名色(
red、lightblue)渲染不一致,一律转成十六进制再映射 - Element UI、Ant Design 等组件库的主题变量(如
$--color-primary)需单独对接,不能指望它们自动响应:root变量 - SVG 内联样式(
fill="#333")和 Canvas 绘图色也得同步处理,否则深色模式下仍刺眼
最易被忽略的一点:HTML 元素自身背景色。很多项目只改了 body 或容器,但 html 根元素没设 background-color: var(--bg-color),页面内容不满屏时,底部/右侧会裸露白底——这不属于“主题没生效”,而是布局层漏了变量绑定。


















