Skip to content
📖预计阅读时长:0 分钟字数:0

话题 6:命名规范深度探讨

本文是「设计系统与 Tailwind CSS 深度实践」系列的最后一篇,深入探讨 Token 命名的哲学、流派与最佳实践。


一、为什么命名如此重要?

1.1 命名的三重影响

影响维度说明
可读性开发者能否快速理解这个 Token 的用途
可维护性修改/扩展时是否容易定位和调整
设计师理解成本设计师能否直接理解代码中的命名

1.2 一个命名失败的案例

css
/* 糟糕的命名 */
:root {
  --c1: #3B82F6;
  --c2: #EF4444;
  --main-color: #111827;
  --sub: #6B7280;
  --bg: #FFFFFF;
  --bgAlt: #F9FAFB;
}

问题:

  • --c1--c2 完全无语义
  • --main-color--sub 是什么的 main/sub?
  • --bg--bgAlt 的区别是什么?
  • 大小写不一致(bgAlt vs main-color

好的命名应该让代码"自解释"


二、三大命名流派深度分析

2.1 流派一:数值型(Primitive-focused)

特点:以具体数值或刻度命名

css
/* 颜色 */
--color-blue-50: #EFF6FF;
--color-blue-500: #3B82F6;
--color-blue-900: #1E3A8A;

/* 间距 */
--space-1: 4px;
--space-2: 8px;
--space-4: 16px;

/* 字号 */
--text-sm: 14px;
--text-base: 16px;
--text-lg: 18px;

优点

  • 无歧义,100 就是比 200 浅
  • 与 Tailwind 默认命名一致
  • 扩展容易(可以加 150、250 等中间值)

缺点

  • 无使用语义(blue-500 用在哪?)
  • 主题切换困难(暗黑模式下 blue-500 该变成什么?)
  • 设计师需要记忆数字含义

适用场景:Primitive Token 层


2.2 流派二:语义型(Semantic-focused)

特点:以使用场景/语义命名

css
/* 背景 */
--color-bg-primary: #FFFFFF;
--color-bg-secondary: #F9FAFB;
--color-bg-inverse: #111827;

/* 文字 */
--color-text-primary: #111827;
--color-text-secondary: #6B7280;
--color-text-muted: #9CA3AF;

/* 边框 */
--color-border-default: #E5E7EB;
--color-border-emphasis: #3B82F6;

/* 交互状态 */
--color-interactive-primary: #3B82F6;
--color-interactive-primary-hover: #2563EB;

优点

  • 语义清晰,知道用在哪
  • 主题切换友好(切换映射即可)
  • 设计师易理解

缺点

  • 命名难度高(什么是 primary vs secondary?)
  • 可能出现命名爆炸
  • 边界模糊(这个蓝色是 primary 还是 brand?)

适用场景:Semantic Token 层


2.3 流派三:组件型(Component-focused)

特点:精确到具体组件和状态

css
/* Button */
--button-primary-bg: #3B82F6;
--button-primary-bg-hover: #2563EB;
--button-primary-bg-active: #1D4ED8;
--button-primary-bg-disabled: #E5E7EB;
--button-primary-text: #FFFFFF;
--button-primary-text-disabled: #9CA3AF;

/* Input */
--input-bg: #FFFFFF;
--input-border: #E5E7EB;
--input-border-focus: #3B82F6;
--input-border-error: #EF4444;
--input-text: #111827;
--input-placeholder: #9CA3AF;

优点

  • 精确无歧义
  • 组件完全自包含
  • 修改影响范围明确

缺点

  • Token 数量爆炸
  • 维护成本高
  • 复用困难(按钮和卡片都想用同一个蓝色怎么办?)

适用场景:大型设计系统的 Component Token 层


2.4 三种流派对比总结

维度数值型语义型组件型
可读性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
灵活性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
主题支持⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Token 数量
维护成本
设计师友好⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

三、我的推荐:分层混合策略

3.1 核心原则

不同层用不同命名策略

层级命名策略示例
Primitive数值型blue-500, gray-100, space-4
Semantic语义型bg-primary, text-muted, border-default
Component组件型(可选)button-primary-bg-hover

3.2 命名结构规范

通用结构:{category}-{property}-{variant}-{state}

category:  color, space, size, radius, shadow, font, ...
property:  bg, text, border, ring, ...
variant:   primary, secondary, muted, success, error, ...
state:     default, hover, active, disabled, focus, ...

3.3 完整命名体系示例

Primitive Layer(数值型)
├── color-blue-50 ... color-blue-950
├── color-gray-50 ... color-gray-950
├── color-red-50 ... color-red-700
├── color-green-50 ... color-green-700
├── space-0 ... space-96
├── radius-none, radius-sm, radius-md, radius-lg, radius-full
└── shadow-sm, shadow-md, shadow-lg, shadow-xl

Semantic Layer(语义型)
├── Color - Background
│   ├── color-bg (默认背景)
│   ├── color-bg-secondary (次级背景)
│   ├── color-bg-tertiary (三级背景)
│   ├── color-bg-inverse (反转背景)
│   └── color-bg-overlay (遮罩背景)

├── Color - Text
│   ├── color-text (默认文字)
│   ├── color-text-muted (弱化文字)
│   ├── color-text-subtle (更弱文字)
│   ├── color-text-inverse (反转文字)
│   └── color-text-on-primary (主色上的文字)

├── Color - Border
│   ├── color-border (默认边框)
│   ├── color-border-muted (弱化边框)
│   └── color-border-emphasis (强调边框)

├── Color - Interactive
│   ├── color-primary (主要交互色)
│   ├── color-primary-hover
│   ├── color-primary-active
│   ├── color-secondary (次要交互色)
│   └── color-accent (强调色)

├── Color - Status
│   ├── color-success / color-success-bg / color-success-text
│   ├── color-warning / color-warning-bg / color-warning-text
│   ├── color-error / color-error-bg / color-error-text
│   └── color-info / color-info-bg / color-info-text

└── Color - Misc
    ├── color-ring (焦点环)
    └── color-shadow (阴影色)

四、常见命名争议与我的立场

4.1 争议 1:primary 还是 brand?

css
/* 方案 A: primary */
--color-primary: #3B82F6;

/* 方案 B: brand */
--color-brand: #3B82F6;

我的立场:用 primary

理由:

  • primary 是 UI 语境,描述"最重要的交互色"
  • brand 是营销语境,可能有多个品牌色
  • Tailwind、shadcn/ui、Radix 等主流方案都用 primary
  • 更通用,不绑定具体品牌概念

4.2 争议 2:default 还是省略?

css
/* 方案 A: 显式 default */
--color-bg-default: #FFFFFF;
--color-bg-secondary: #F9FAFB;

/* 方案 B: 省略 default */
--color-bg: #FFFFFF;
--color-bg-secondary: #F9FAFB;

我的立场:省略 default

理由:

  • 更简洁
  • default 是隐含的
  • Tailwind 的 DEFAULT 就是这个思路(bg-background 而非 bg-background-default

4.3 争议 3:kebab-case 还是 camelCase?

css
/* 方案 A: kebab-case */
--color-bg-primary: #FFFFFF;

/* 方案 B: camelCase */
--colorBgPrimary: #FFFFFF;

我的立场:CSS 变量用 kebab-case,JS 对象用 camelCase

css
/* CSS */
--color-bg-primary: #FFFFFF;
javascript
// JavaScript
const tokens = {
  color: {
    bgPrimary: '#FFFFFF',
  }
};

理由:

  • 遵循各语言的惯例
  • CSS 变量用 kebab-case 是 CSS 的标准风格
  • 构建工具可以自动转换

4.4 争议 4:嵌套层级多深合适?

css
/* 方案 A: 扁平 */
--button-primary-bg-hover: #2563EB;

/* 方案 B: 嵌套(用对象表示) */
button.primary.bg.hover: #2563EB

我的立场:语义层最多 3 级,组件层最多 4 级

语义层:{category}-{property}-{variant}
        color-bg-secondary ✅
        color-bg-secondary-hover ❌ (hover 应该在组件层)

组件层:{component}-{variant}-{property}-{state}
        button-primary-bg-hover ✅
        button-primary-outline-bg-hover ❌ (太深了)

五、实战命名规范手册

5.1 颜色命名

✅ 推荐命名

背景色:
- background / bg-secondary / bg-tertiary / bg-inverse
- bg-overlay (遮罩)
- bg-raised (浮起,如卡片)

文字色:
- foreground / text-muted / text-subtle / text-inverse
- text-on-primary (主色按钮上的文字)

边框色:
- border / border-muted / border-emphasis

交互色:
- primary / primary-foreground
- secondary / secondary-foreground
- accent / accent-foreground

状态色:
- destructive / destructive-foreground (或 error)
- success / success-foreground
- warning / warning-foreground

❌ 避免的命名

- main, sub (太模糊)
- color1, color2 (无语义)
- light-blue, dark-gray (混淆 primitive 和 semantic)
- btn-color (缩写不一致)

5.2 间距命名

✅ 推荐:数值刻度

space-0, space-1, space-2, space-3, space-4 ...
(基于 4px 基准:0, 4px, 8px, 12px, 16px ...)

✅ 也可以:语义别名(可选)

spacing-page-x (页面水平内边距)
spacing-page-y (页面垂直内边距)
spacing-stack-sm / md / lg (堆叠元素间距)
spacing-inline-sm / md / lg (行内元素间距)

❌ 避免

spacing-small (small 是多少?)
padding-1 (把 padding 和 space 混淆)

5.3 字体命名

✅ 推荐

字号:text-xs, text-sm, text-base, text-lg, text-xl ...
字重:font-normal, font-medium, font-semibold, font-bold
字族:font-sans, font-mono, font-serif

行高(可以绑定到字号):
fontSize: {
  sm: ['14px', { lineHeight: '20px' }],
}

❌ 避免

font-size-1, font-size-2 (数字无含义)
font-big, font-bigger (相对概念)

5.4 圆角命名

✅ 推荐

radius-none (0)
radius-sm (4px)
radius (6px,默认)
radius-md (8px)
radius-lg (12px)
radius-xl (16px)
radius-full (9999px)

❌ 避免

radius-1, radius-2 (数字无含义)
border-radius-small (太长)
rounded-4 (与 Tailwind 的 rounded 类混淆)

5.5 阴影命名

✅ 推荐

shadow-sm
shadow (默认)
shadow-md
shadow-lg
shadow-xl

或者语义化:
shadow-raised (浮起效果)
shadow-overlay (弹层阴影)
shadow-inset (内阴影)

六、完整命名规范参考表

6.1 CSS 变量命名规范

css
/* ================================================
   命名规范参考
   ================================================
   
   结构:--{category}-{property}-{variant}-{state}
   
   category: color, space, size, radius, shadow, font
   property: bg, text, border, ring
   variant:  primary, secondary, muted, success, error...
   state:    hover, active, disabled, focus (通常在组件层)
   
   ================================================ */

:root {
  /* ============ Colors ============ */
  
  /* Background */
  --color-bg: 255 255 255;
  --color-bg-secondary: 249 250 251;
  --color-bg-tertiary: 243 244 246;
  --color-bg-inverse: 17 24 39;
  --color-bg-overlay: 0 0 0 / 0.5;
  
  /* Text */
  --color-text: 17 24 39;
  --color-text-muted: 107 114 128;
  --color-text-subtle: 156 163 175;
  --color-text-inverse: 255 255 255;
  
  /* Border */
  --color-border: 229 231 235;
  --color-border-muted: 243 244 246;
  --color-border-emphasis: 59 130 246;
  
  /* Interactive */
  --color-primary: 59 130 246;
  --color-primary-foreground: 255 255 255;
  --color-secondary: 243 244 246;
  --color-secondary-foreground: 17 24 39;
  --color-accent: 99 102 241;
  --color-accent-foreground: 255 255 255;
  
  /* Status */
  --color-success: 34 197 94;
  --color-success-foreground: 255 255 255;
  --color-warning: 234 179 8;
  --color-warning-foreground: 255 255 255;
  --color-error: 239 68 68;
  --color-error-foreground: 255 255 255;
  
  /* Misc */
  --color-ring: 59 130 246;
}

6.2 Tailwind 配置命名规范

javascript
// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      // Primitive (数值型,直接值)
      blue: { 50: '...', 500: '...', 900: '...' },
      gray: { 50: '...', 500: '...', 900: '...' },
      
      // Semantic (语义型,CSS 变量)
      background: {
        DEFAULT: 'rgb(var(--color-bg) / <alpha-value>)',
        secondary: 'rgb(var(--color-bg-secondary) / <alpha-value>)',
        tertiary: 'rgb(var(--color-bg-tertiary) / <alpha-value>)',
      },
      foreground: {
        DEFAULT: 'rgb(var(--color-text) / <alpha-value>)',
        muted: 'rgb(var(--color-text-muted) / <alpha-value>)',
      },
      primary: {
        DEFAULT: 'rgb(var(--color-primary) / <alpha-value>)',
        foreground: 'rgb(var(--color-primary-foreground) / <alpha-value>)',
      },
      // ...
    }
  }
}

七、你的组件库命名建议

基于你的场景(个人组件库 + 多主题 + React),我的具体建议:

7.1 采用两层命名

不需要组件层 Token(太复杂),两层足够:

Layer 1: Primitive(数值型)
├── 在 tailwind.config.js 中定义
├── 直接用 Tailwind 默认命名习惯
└── blue-500, gray-100, space-4 ...

Layer 2: Semantic(语义型)
├── 在 globals.css 中用 CSS 变量定义
├── 用于支持主题切换
└── background, foreground, primary, muted ...

7.2 命名速查表

用途Tailwind ClassCSS 变量
默认背景bg-background--color-bg
次级背景bg-background-secondary--color-bg-secondary
默认文字text-foreground--color-text
弱化文字text-foreground-muted--color-text-muted
主要交互色bg-primary--color-primary
主色上的文字text-primary-foreground--color-primary-foreground
默认边框border-border--color-border
焦点环ring-ring--color-ring
错误状态text-destructive--color-error
成功状态text-success--color-success

7.3 使用示例

jsx
// 组件中这样使用
function Button({ variant = 'primary', children }) {
  const variants = {
    primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
    secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
    outline: 'border border-border bg-background hover:bg-background-secondary',
    ghost: 'hover:bg-background-secondary',
    destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
  };
  
  return (
    <button className={`px-4 py-2 rounded-md font-medium ${variants[variant]}`}>
      {children}
    </button>
  );
}

// 页面中这样使用
function Page() {
  return (
    <div className="min-h-screen bg-background text-foreground">
      <header className="border-b border-border p-4">
        <h1 className="text-xl font-bold">Dashboard</h1>
      </header>
      <main className="p-6">
        <div className="rounded-lg border border-border bg-background-secondary p-4">
          <p className="text-foreground-muted">描述文字</p>
          <Button variant="primary">确认</Button>
        </div>
      </main>
    </div>
  );
}

八、系列总结

6 个话题核心要点回顾

话题核心结论
1. Token 概念Token 是设计决策的最小单元,不是 CSS 变量;至少需要 Primitive + Semantic 两层
2. Tailwind 哲学约束式设计带来一致性;config 就是 Primitive Token 层
3. 技术选型推荐 Tailwind;Runtime CSS-in-JS 正在衰落
4. 多主题实现CSS 变量 + class 切换;用 RGB 格式支持透明度
5. 工程化方案先用 TS 直接定义,成熟后引入 Style Dictionary
6. 命名规范Primitive 用数值型,Semantic 用语义型;省略 default

你的行动清单

  1. 立即可做

    • 创建 src/tokens/ 目录,定义 Primitive Token
    • 创建 src/styles/globals.css,定义语义化 CSS 变量
    • 配置 tailwind.config.ts,引用 Token
  2. 组件开发时

    • 使用语义化颜色(bg-backgroundtext-primary
    • 不要硬编码颜色值(bg-[#3B82F6]
    • 封装可复用的变体(如 Button 的 variant)
  3. 未来演进

    • 引入 Style Dictionary 自动化构建
    • 拆分 Monorepo 结构
    • 考虑 Figma Token 同步

文件清单总览

src/
├── tokens/
│   ├── index.ts           # 统一导出
│   ├── colors.ts          # Primitive 颜色
│   ├── spacing.ts         # 间距刻度
│   ├── typography.ts      # 字体相关
│   └── semantic.ts        # 语义化 Token(CSS 变量引用)
├── styles/
│   └── globals.css        # CSS 变量定义(Light/Dark)
├── hooks/
│   └── useTheme.ts        # 主题切换逻辑
├── components/
│   └── ...
└── tailwind.config.ts     # Tailwind 配置

结语

设计系统不是一蹴而就的,而是渐进演化的。

从最简单的方案开始:

  1. 先让主题切换跑起来
  2. 再逐步完善 Token 体系
  3. 最后考虑工程化和团队协作

完美是好的敌人。先有一个能用的系统,比有一个完美但从未实现的设计更有价值。

祝你的组件库项目顺利!🎉