变量应分框架级、品牌级、实例级三层管理:框架级仅含几何与排版基础值并定义在:root;品牌级须绑定HTML类名限定作用域;实例级由JS运行时注入;所有组件样式必须通过语义化中间变量(如--btn-bg)解耦,禁用直接引用品牌变量。

变量必须分三层:框架级、品牌级、实例级
混在一起写 --color-primary 然后让各品牌覆盖,是调试卡死和样式漏改的根源。框架级变量只放真正不变的基建值,比如 --spacing-xs、--radius-sm、--font-family-base,全部定义在 :root;品牌级变量必须用类名限定作用域,例如 .brand-a { --color-primary: #0066cc; };实例级变量由 JS 运行时注入,比如弹窗主题色或用户偏好暗色开关,不能写死在 CSS 里。
常见错误现象:--color-primary 在 A 品牌生效,B 品牌却用了旧值——因为没加 .brand-b 作用域,被上层样式覆盖了;或者某组件内联 style 设置了 --color-primary,结果所有子元素都继承错乱。
- 框架级变量禁止出现颜色、阴影、边框等视觉属性,只保留几何与排版基础值
- 品牌级变量必须绑定到 HTML 根元素类名(
<html class="brand-a">),不能只加在某个容器上 - 实例级变量建议用
style.setProperty()注入,避免污染全局作用域
品牌变量不能直接赋给组件,要加中间变量解耦
写 button { background: var(--color-primary); } 看似简洁,实则断掉了品牌定制入口。一旦 B 品牌想让按钮背景用渐变而非纯色,就只能重写整条规则——破坏原子性,也绕过变量体系。
正确做法是引入一层语义中间变量:button { background: var(--btn-bg, var(--color-primary)); }。这样品牌只需覆盖 --btn-bg,不影响 --color-primary 的其他用途。
立即学习“前端免费学习笔记(深入)”;
- 每个基础组件(
button、input、card)至少预留 2–3 个可覆盖中间变量,如--btn-bg、--btn-text、--btn-border - 中间变量默认值必须调用品牌级变量,但不能硬编码 HEX,否则无法响应深色模式切换
- 禁止在组件样式里直接写
var(--color-primary),一律走中间层
PostCSS 插件比 JS 注入更稳,尤其对 SSR 和伪元素
用 JS 读取 getComputedStyle 再计算 HSL 补色,看似灵活,但在 SSR 渲染、::before 伪元素、未挂载组件中根本拿不到 computed style,导致 FOUC 或 fallback 色失效。
构建期处理才是多品牌项目的底线保障。比如用 postcss-hsl-calc 把 hsl(from var(--primary) calc(h + 180) s l) 展开为静态值,或用自定义插件按品牌配置批量生成 .brand-a .ui-button 对应的变量映射表。
- SSR 页面首屏必须靠构建期输出确定 CSS,JS 注入永远滞后
- 伪元素、
@keyframes、content属性不支持运行时变量计算 - PostCSS 插件可结合品牌 JSON 配置自动注入差异样式,无需手动维护多套 CSS 文件
Tailwind 中扩展颜色必须用 extend.colors,且色阶要显式定义
theme.colors 是顶层替换入口,写成 colors: { primary: '#3b82f6' } 会清空所有内置色(bg-blue-500、text-gray-700 全失效),不是配置没生效,是整个颜色系统被重置了。
自定义色名如 brand-accent 必须显式定义色阶对象:'brand-accent': { '50': '#f3f4f6', '500': '#8b5cf6', '900': '#4c1d1c' }。单值写法 'brand-accent': '#8b5cf6' 只生成 bg-brand-accent,不支持 -500 后缀。
- 务必检查
content配置是否覆盖源文件路径,否则 JIT 编译不扫描到新 class - 改完
tailwind.config.js必须重启 dev server,热更新不重载配置 - SVG
fill、输入框placeholderColor不自动继承 colors,需手动在theme.extend下桥接并用 CSS 变量


















