语义色 Token 的价值,是把“这个颜色是什么”转换为“这个颜色在界面中承担什么角色”。当按钮、文字和状态不再直接引用 Blue 500,主题切换、品牌升级和可访问性调整才能真正规模化。
很多团队已经开始使用颜色变量,但打开 Figma 仍然会看到 Button background = Blue/600、Error text = Red/500、Dark Mode 又复制一套 Blue-dark。这样的变量可以批量替换颜色,却没有建立稳定的语义层。真正的 Color Token 系统应该让组件依赖“角色”,而不是依赖某个色板编号。
01 一、先理解四个层级:Value、Primitive、Semantic、Component
以 Carbon 当前颜色文档为例,它把 Token 定义为角色型标识符,Theme 决定每个角色最终使用的具体颜色值;同一个 text-secondary 在不同主题可以映射到不同灰阶。这个模型比“颜色编号直接进组件”更适合长期维护。
- Value:最终可渲染值,例如 #0F62FE。
- Primitive:品牌或基础色板,例如 blue-60、gray-100。
- Semantic:界面角色,例如 text-primary、border-subtle、support-error。
- Component:只属于特定组件的语义,例如 button-primary-background-hover。
02 二、为什么语义名称比颜色名称更稳定?
假设“主要文字”现在是 Gray 100,Dark Mode 下可能变成 Gray 10。如果组件写死 gray-100,就必须在主题切换时逐个覆盖;如果使用 text-primary,只需要 Theme 改映射。品牌从蓝色升级成紫色时,interactive-primary 仍然是“主要操作”,语义不变。

03 三、语义 Token 要描述角色,不要夹带实现细节
推荐的命名维度通常包括对象 + 强度/角色 + 状态,例如 text-primary、text-secondary、border-strong、background-hover、support-error。Carbon 当前的核心色 Token 也按 Background、Layer、Field、Border、Text、Link、Icon、Support、Focus 等角色分组。
避免命名为 blue-button 或 dark-gray-text,因为一旦主题或品牌变化,名称就开始撒谎。
04 四、状态色不能只等于红黄绿
Error、Warning、Success、Info 是语义,不是色相。状态 Token 应同时定义文本、图标、边框、背景等层级,并确保不靠颜色单独传达含义。一个错误状态最好同时有错误文案或图标,而不是只把输入框变红。
05 五、Dark Mode 不应该复制一套组件样式
最理想的主题机制是:组件只引用同一组语义 Token,Theme 负责切换值。Carbon v11 将颜色 Token 通过 CSS Custom Properties 提供,使局部主题和 Light/Dark 切换更容易。设计端也应该保持相同结构,而不是复制“Button Dark”整套组件。

06 六、层级背景需要 Contextual Token
复杂产品常有 Page → Card → Nested panel → Input 多层背景。如果只有 background-default 和 background-subtle,很快会出现“这里再加一个灰”。可以建立 Layer / Surface 层级,组件根据所在上下文引用相对角色。Carbon 的 layering token 就是为这种嵌套场景设计的。
07 七、什么时候需要 Component Token?
如果所有按钮都能用 interactive-primary、text-on-primary 组合,不必提前创建几十个 Button Token。但当某个组件存在特殊状态、未来需要独立主题或公共 Token 无法表达其语义时,可以增加组件级别。Component Token 应该是最后一层,不应该成为逃避语义建模的捷径。

08 八、无障碍检查要在 Token 层做,也要在组件层做
即使 Primitive 色板单独看对比度很好,组合成 text-secondary on layer-02 后仍可能不达标。Token 文档应给出允许搭配,并在组件测试里验证实际组合。Focus、错误边框和图形等非文本元素还需要关注 WCAG 2.2 的 Non-text Contrast。
09 九、Token 迁移不能只做全局替换
从 Blue/600 迁移到 Semantic Token 时,先分析它在不同场景承担的角色。同一个 Blue/600 可能同时用于链接、按钮、图表和选中状态,这些应该拆成不同语义 Token,而不是把所有实例批量替换为 interactive-primary。迁移过程本身就是一次语义审计。
10 十、建立可长期维护的颜色工作流
- 保留品牌 Primitive 色板,但禁止业务组件直接随意引用。
- 建立核心 Semantic Token,并记录角色与允许场景。
- 为 Light、Dark、品牌主题提供值映射。
- 只在必要时增加 Component Token。
- 把 Token 同步到设计工具和代码,并让主题切换自动验证。
- 每次新增颜色先问:是新语义,还是旧语义没有被正确建模?
当团队开始用“text-secondary 是否合适”而不是“这个灰再浅一点”讨论颜色时,颜色系统才从视觉规范升级成了可维护的产品基础设施。
常见问题
Primitive Color 和 Semantic Token 有什么区别?
Primitive 表示基础色值或色阶,Semantic Token 表示在界面中的用途。组件通常应该优先引用语义层。
是否应该完全禁止开发使用 Hex?
生产组件最好通过 Token 管理。特殊数据可视化、品牌内容等可以有明确例外,但应避免在业务代码中随机硬编码。
Dark Mode 需要一套新的 Token 名称吗?
通常不需要。相同语义 Token 在不同 Theme 中映射到不同值,更有利于维护。
Component Token 越多越好吗?
不是。组件 Token 过多会让系统失去共享语义。只有公共 Token 无法表达稳定需求时再增加。
状态色可以只用红黄绿吗?
不建议。颜色不应成为唯一信息通道,状态还应通过文字、图标、形状等方式表达,并满足对比度要求。