不能在 tailwind.config.js 的 theme.extend.colors 中直接使用 var(--primary),因为 Tailwind 构建时需静态解析颜色值以生成色阶、透明度及暗化变体,而 CSS 变量是运行时才求值的字符串,无法提取 RGB 分量,导致构建报错或样式失效。

不能在 tailwind.config.js 里直接把 var(--primary) 当颜色值塞进 theme.extend.colors——它不会生成色阶、hover 变体会崩、构建时报 Cannot read property 'r' of undefined,这不是配置错,是 Tailwind 的设计限制。
为什么 var(--x) 不能直接写进 colors 扩展里
Tailwind 的颜色插件在构建时要静态解析每个颜色值,用来生成 -50 到 -900 色阶、透明度叠加(如 bg-primary/20)、暗化逻辑(hover:bg-primary-600)。而 var(--primary) 是运行时才求值的字符串,JS 配置文件加载时根本没执行 CSS,parseColor() 拿到的是字面量 "var(--primary)",无法提取 r/g/b 分量。
常见现象包括:
-
bg-primary能生成,但bg-primary-500类完全不出现 -
hover:bg-primary渲染出color: rgb(NaN)或直接报错 - 深色模式下用
dark:bg-primary无效,因为变量本身没切换逻辑
想复用固定色值?直接写 HEX,别碰 var()
如果你只是把设计系统里的品牌色(比如 --color-brand: #1677FF)当一个新色名用,不需要运行时切换,就别绕路。这是最稳、最兼容、零风险的做法。
立即学习“前端免费学习笔记(深入)”;
tailwind.config.js 中这样写:
module.exports = {
theme: {
extend: {
colors: {
brand: '#1677FF',
},
},
},
}
之后就能直接用 text-brand、bg-brand-500、hover:bg-brand-600,所有变体自动可用。
真需要运行时切换(如主题切换)?绕过 config,用 @layer utilities + var()
当你要支持用户点击切换主题、深色模式响应 prefers-color-scheme、或 JS 动态改 document.documentElement.style.setProperty('--color-primary', ...) 时,必须放弃在配置里“映射”,改用 CSS 层级绑定。
在你的主 CSS 文件(如 src/index.css)里写:
@layer utilities {
.text-brand { @apply text-[var(--color-brand)]; }
.bg-brand { @apply bg-[var(--color-brand)]; }
.border-brand { @apply border-[var(--color-brand)]; }
}
同时确保全局已定义该变量:
:root {
--color-brand: #1677FF;
}
@media (prefers-color-scheme: dark) {
:root {
--color-brand: #2563eb;
}
}
要点:
- 不要在
theme.extend里重复定义同名键,否则会冲突 -
@apply text-[var(--x)]是安全的,Tailwind v3.3+ 支持方括号语法解析 CSS 变量 - 这种写法不依赖构建时解析,所有变体(
dark:、hover:)需手动加前缀,例如dark:text-brand有效,但hover:text-brand不会自动暗化——你得自己控制变量值
Tailwind v4 用户:优先用 @theme 规则
v4 原生支持 @theme at-rule,它能在 CSS 层声明变量并让 Tailwind 自动绑定为工具类,比手写 @layer utilities 更干净。
在 src/index.css 中:
@theme {
--color-primary: #1677FF;
--color-secondary: #6b7280;
}
@tailwind base;
@tailwind components;
@tailwind utilities;
保存后即可使用 text-primary、bg-secondary 等类,且自动支持 dark: 前缀(前提是 :root 或媒体查询里也定义了对应暗色变量)。
注意:@theme 不处理色阶推导,所以 bg-primary-500 依然不会生成——它只做 1:1 映射,适合你明确只要一个固定色值的场景。
最容易被忽略的一点:无论选哪种方式,CSS 变量的定义位置和作用域必须对齐。写在 .dark 选择器里、但没配 darkMode: "class",或者 JS 修改了 style.setProperty 却忘了触发重绘,都会让变量看起来“没生效”。调试时先检查 getComputedStyle(document.documentElement).getPropertyValue('--color-brand') 返回什么,再看类是否真的应用到了元素上。


















