设计系统
设计令牌
色彩变量
如何用一套设计令牌,统一四条产品线的视觉语言
当团队同时维护电商、博客、后台与移动端时,最大的挑战不是组件数量,而是如何让它们说同一种语言。本文拆解我们在 8 个月内完成的令牌体系迁移。
陈
陈思远
产品设计负责人 · Nexus Design
2026-10-01 发布
·
18 分钟阅读 · 3,842 次浏览
封面图 · 设计令牌体系总览
一、为什么需要设计令牌
在 2025 年初,Nexus 同时维护着四条产品线:面向消费者的商城、内容博客、内部后台系统以及移动端 App。每条线都有自己的一套颜色、间距与圆角定义,结果是同一个「品牌主色」出现了 7 个略有差异的十六进制值。
这不是设计问题,而是协作接口的问题。当颜色以硬编码的形式散落在四个仓库里时,任何一次品牌调整都会变成一场跨团队的考古。
令牌不是「把颜色抽成变量」这么简单,它的真正价值在于:让设计决策成为可被引用、可被审计、可被机器校验的一等公民。
二、三层令牌结构
我们最终采用了业界通行的三层结构,并在命名上做了严格约束:
- 基础令牌(Primitive):纯粹的色阶与尺寸刻度,如
--c-zinc-100、--sp-4。这一层不含语义,只描述「是什么」。 - 语义令牌(Semantic):描述用途,如
--c-bg、--c-fg-2、--c-danger。业务代码只允许引用这一层。 - 组件令牌(Component):仅在必要时存在,如
--btn-h-lg,用于吸收组件级别的特例。
:root {
/* 基础令牌 —— 只描述客观色阶 */
--c-zinc-50: #FAFAFA;
--c-zinc-900: #18181B;
--sp-4: 16px;
/* 语义令牌 —— 业务代码只引用这一层 */
--c-bg: var(--c-zinc-50);
--c-fg: var(--c-zinc-900);
--c-bd: #E4E4E7;
}
[data-theme="dark"] {
--c-bg: var(--c-zinc-900);
--c-fg: var(--c-zinc-50);
--c-bd: #27272A;
}
三、迁移路径:用 8 周换两年效率
迁移最大的风险不是技术,而是业务节奏。我们没有选择「停下来重构」,而是用增量替换的方式推进:
| 阶段 | 周期 | 目标 | 验收标准 |
|---|---|---|---|
| 建库 | 第 1-2 周 | 梳理全部硬编码值,产出基础与语义令牌 | 覆盖率 ≥ 92% |
| 并行 | 第 3-5 周 | 新旧两套令牌并存,新代码强制走语义层 | 新增硬编码 = 0 |
| 替换 | 第 6-7 周 | 批量替换存量引用并回归视觉快照 | 快照差异 < 0.5% |
| 收口 | 第 8 周 | 移除旧变量,接入 CI 校验 | Lint 规则全量生效 |
3.1 CI 校验:让规范可执行
规范如果只写在文档里,三个月后就会失效。我们把「禁止硬编码颜色」做成了构建期检查:
const HARDCODED = /#[0-9a-f]{3,8}\b/i;
for (const file of files) {
const src = read(file);
if (HARDCODED.test(src)) {
fail(file + ' 出现硬编码颜色,请改用语义令牌');
}
}
一个容易被忽略的细节
深色模式下的状态色需要单独调校:直接把浅色模式的红色搬到深色背景上,饱和度会显得刺眼。我们为每个状态色准备了深浅两套值。
四、常见误区
- 把令牌当主题系统用。令牌解决的是命名与引用问题,不是多主题切换问题,两者要分层设计。
- 语义层命名过细。
--c-button-primary-hover-bg这类命名会让令牌表迅速膨胀,且难以复用。 - 忽略迁移成本。存量代码的统一替换必须配合视觉快照回归,否则会引入难以定位的样式回归。
五、结果与后续
迁移完成后,品牌色调整从「预计两周」缩短到「半天」。更重要的是,四条产品线终于可以在同一张设计稿上被评审。
下一步我们计划把令牌接入设计工具的变量系统,实现设计稿与代码之间的双向同步。
相关推荐
related图标系统的一致性:从网格到笔画重量
7 分钟阅读 · 1,340 次浏览
深色模式不是反色:色彩系统重构
12 分钟阅读 · 4,210 次浏览
从 0 到 1 搭建前端组件库的 7 个关键决策
6 分钟阅读 · 2,104 次浏览
评论
86 comments
陈
支持 Markdown · 请友善发言
王
王蒙前端工程师2026-10-02 10:14
CI 校验这一条特别有共鸣。我们团队也是把「禁止硬编码颜色」做成了 lint 规则,效果比写十页规范文档都好。
李
李彦2026-10-01 22:38
三层结构的命名约定能否展开讲讲?我们卡在语义层粒度上很久了,尤其是「卡片边框」这种既像基础又像语义的值。
陈陈思远作者
我们的判定标准是:这个值会不会因为「主题」而变。会变就放语义层,不会变就留在基础层。
赵
赵雪设计工程师2026-10-01 18:05
迁移阶段的「并行」策略很实用。我们之前一次性替换,结果回归测试跑了三周。