Tailwind.config.js 中 theme.extend.colors 不支持 CSS 变量如 var(--primary),必须用静态值;动态变量需通过 safelist 配置并配合 HTML 中的任意值语法(如 bg-[var(--bg-surface)])才能生效,且变量须定义在 @layer base 的 :root 或 [data-theme] 中。

tailwind.config.js 里不能写 var(--primary)
因为 Tailwind 是构建时工具,tailwind.config.js 中的 theme.extend.colors 必须是静态值(如 "#3b82f6" 或 rgb(59, 130, 246)),写 var(--primary) 会被忽略或报错,且不会生成任何 CSS 规则。常见现象是:类名如 bg-primary 在 DevTools 里完全查不到对应样式。
真正能响应运行时变化的,只有在 HTML/JSX 中显式写出的任意值语法,比如:bg-[var(--bg-surface)]、text-[color:var(--text-primary)]。这些字符串必须实际出现在源码中,Tailwind 才会扫描并生成规则。
- 变量名必须以
--开头,只含字母、数字、连字符、下划线,不能有空格或中文 - 方括号内不能有空格:
bg-[var(--bg-surface)]✅,bg-[var( --bg-surface )]❌ - VS Code 插件标红 ≠ 编译失败,只要配置正确,就能通过
必须配 safelist 或 content 扫描路径
Tailwind 默认跳过无法静态分析的 [var(...)] 表达式。不主动放行,bg-[var(--bg-surface)] 就不会进最终 CSS 文件。
推荐在 tailwind.config.js 中配置:
立即学习“前端免费学习笔记(深入)”;
safelist: [ /^bg-\[.*\]$/, /^text-\[.*\]$/, /^border-\[.*\]$/, 'bg-[var(--bg-surface)]', 'text-[color:var(--text-primary)]', 'border-[color:var(--border-muted)]' ]
同时确保 content 覆盖所有使用这些字符串的文件:
content: ['./src/**/*.{js,jsx,ts,tsx,html}']
- 正则方式更省心,但会略增打包体积;精确列表更安全,适合主题变量稳定的小型项目
- 如果用
data-theme="dark",也要把[data-theme="dark"]加入safelist,否则 PurgeCSS 可能删掉整块覆盖规则
变量定义必须写在 @layer base 里,且挂到 :root 或 [data-theme]
CSS 变量必须在渲染前就存在,且作用域要足够宽。最稳妥的方式是:
- 把默认变量写在
@layer base块内,并放在:root下 - 每个主题用
[data-theme="xxx"]覆盖,而不是靠 class 或局部 style -
data-theme必须设在<html>标签上,避免子元素继承断裂
示例:
@layer base {
:root {
--bg-surface: #ffffff;
--text-primary: #1e293b;
--border-muted: #e2e8f0;
}
[data-theme="dark"] {
--bg-surface: #0f172a;
--text-primary: #f1f5f9;
--border-muted: #334155;
}
}
注意:@layer base 必须在所有 Tailwind 默认样式之前加载,否则变量可能被覆盖。
JS 切换时最容易漏掉三件事
执行 document.documentElement.setAttribute('data-theme', 'dark') 后页面闪白、颜色错位、部分组件没变色,通常是因为:
- 没提前在
<head>内联兜底变量,首屏渲染时var(--x)还未定义,回退为inherit或透明 - 混用了
text-blue-500和text-[color:var(--text-primary)]—— 前者设置了color+font-weight,后者只设color,直接被覆盖 - 没同步设置 alpha 通道变量,导致
bg-primary/70类失效(它依赖rgb(var(--primary) / var(--primary-alpha, 1))结构)
建议切换逻辑封装成函数,批量调用 document.documentElement.style.setProperty(),并统一命名前缀(如全用 --theme- 开头),避免项目里出现 --primary、--color-primary、--main-color 并存的情况。



















