前端设计系统建设复盘:Design Token从理念到代码的落地全过程
一、设计的不一致性有多贵
某SaaS产品的UI经历2年开发后,积累了82种灰色值(不同组件用了不同的gray-100)、14种主色调变体、7套不同的圆角规则。设计师抱怨"开发实现的总是跟设计稿不一样",开发抱怨"设计规范变了我怎么知道改了哪"。
目标是建立"单一真相来源"——它不是口头约定的规范,而是代码化的约束,任何变更都能自动同步到所有组件。
二、从Figma到代码的Token管道
第一步:在Figma中定义Variables
设计师在Figma中集中管理Design Variables——颜色、字体、间距、阴影、圆角。通过Figma Variables插件导出为JSON。
第二步:Style Dictionary做多平台转换
// tokens.json —— 中间格式 { "color": { "primary": { "500": { "value": "#4F46E5" }, "600": { "value": "#4338CA" } }, "neutral": { "100": { "value": "#F3F4F6" }, "200": { "value": "#E5E7EB" }, "900": { "value": "#111827" } } }, "spacing": { "xs": { "value": "4px" }, "sm": { "value": "8px" }, "md": { "value": "16px" }, "lg": { "value": "24px" } }, "typography": { "heading": { "xl": { "value": { "fontFamily": "Inter", "fontSize": "32px", "lineHeight": "40px", "fontWeight": "700" } } } } }// build-tokens.js —— Style Dictionary 配置 const StyleDictionary = require('style-dictionary'); StyleDictionary.extend({ source: ['tokens/**/*.json'], platforms: { css: { transformGroup: 'css', buildPath: 'dist/css/', files: [{ destination: 'variables.css', format: 'css/variables', options: { outputReferences: true, }, }], }, js: { transformGroup: 'js', buildPath: 'dist/js/', files: [{ destination: 'tokens.js', format: 'javascript/es6', }], }, }, }).buildAllPlatforms();输出:
/* dist/css/variables.css */ :root { --color-primary-500: #4F46E5; --color-primary-600: #4338CA; --color-neutral-100: #F3F4F6; --color-neutral-200: #E5E7EB; --spacing-xs: 4px; --spacing-sm: 8px; --spacing-md: 16px; --typography-heading-xl-font-family: Inter; --typography-heading-xl-font-size: 32px; }// dist/js/tokens.js export const colorPrimary500 = '#4F46E5'; export const spacingMd = '16px';第三步:组件库100%引用Token
<!-- Button.vue —— 零硬编码值 --> <template> <button :class="buttonClasses"> <slot /> </button> </template> <style scoped> .btn { padding: var(--spacing-sm) var(--spacing-md); background: var(--color-primary-500); color: var(--color-neutral-100); border-radius: var(--radius-md); font-family: var(--typography-body-md-font-family); font-size: var(--typography-body-md-font-size); &:hover { background: var(--color-primary-600); } } </style>三、Token变更的自动化传播
流程:设计师改Figma Variables → 导出JSON → CI中运行Style Dictionary → 生成新的CSS/JS → 自动创建PR → Review合并 → npm publish新版本组件库
# .github/workflows/token-update.yml name: Token Update on: push: paths: ['tokens/**/*.json'] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run build:tokens - name: Create PR uses: peter-evans/create-pull-request@v6 with: title: 'Token更新:设计规范变更' body: | 自动检测到Token文件的变更。 请确认变更符合设计意图后合并。 branch: token-update四、Token落地的实际挑战
挑战一:历史组件的迁移。82种灰色值不可能一次性全部Token化。采取"增量迁移"——新组件用Token,老组件逐步改造。每次改老组件时,将其硬编码值替换为Token引用。6个月内老组件Token覆盖率从0%升至85%。
挑战二:Token的命名共识。设计团队和开发团队对命名有分歧。设计师习惯用"Primary/Secondary",开发者习惯用"蓝色/灰色"。最终采用了设计团队主导的语义化命名(如color-primary-500)——因为命名面向的是"视觉意图"而非"颜色值"。
挑战三:暗色模式的Token设计。不是if dark then #000 else #FFF——而是定义语义Token(如color-surface、color-text-primary),每套主题各自赋值:
:root { --color-surface: #FFFFFF; --color-text-primary: #111827; } [data-theme="dark"] { --color-surface: #1F2937; --color-text-primary: #F9FAFB; }五、总结
Design Token体系的核心价值:
- 设计与开发的"单一真相来源"。设计师改颜色,不需要通知开发者——Token自动同步。
- 多平台一致性。Web、iOS、Android从同一份Token源生成各自的代码——品牌色真正统一。
- 暗色模式/品牌白标等主题切换变得简单——换一套Token值即可,代码不变。
Token化的代价:需要设计师学习Figma Variables,开发者学习Style Dictionary配置,CI/CD管道的维护。但对于3人以上团队的中大型产品,这个投资在6个月内即可收回——从"设计师-开发者-测试"三方沟通成本中节省出来的时间,远超搭建Token体系的时间投入。
最大的经验:Token不是"写一份规范文档让大家遵守",而是"代码强制约束,不遵守就无法编译"。硬编码的颜色值被ESLint规则禁止后,Token覆盖率从"纸面上的100%"变成"代码检查器验证过的100%"。这才是"落地"的真正含义。