随着近几年 Figma 等一系列在线设计工具的崛起,相信设计师对设计系统的都有了更深的了解。其实设计系统的建设是一个非常庞大而复杂的工程。我们通过各种设计规范等对产研流程提效,但还是会经常遇到一些棘手的问题。
1. 开发用的颜色/字体样式/投影等与设计稿存在差距;
2. 颜色选择困难。不同设计师之间在用各种层级的文本颜色时,到底用 Gray1 还是用 Gray2,不知道该选哪一种;
3. SaaS 类的产品需要根据客户的品牌色调整产品的主色,设计和开发都面临巨大的工作量;
4. 设计稿的更新无法及时在开发者的代码中体现,一是因为开发首先需要拿到新的设计稿,再根据标注甚至肉眼判断区别后更新代码;另一方面,设计稿中看似简单的改动可能导致较大范围的代码改动,例如字体大小等;
为了解决和优化上述的问题,Design Token 应运而生。它可以高效地解决产品设计和开发过程中的细节和风格一致性的问题,提高产研团队设计质量和协作效率。
什么是 Design Token
"Token"原本的意思是"令牌,指令",与 Design 连在⼀起指"设计变量"。在工程逻辑中用于用户身份与服务器端进行验证,而在设计体系中,Design Token 则可以简单理解为封装的视觉样式参数。它通过规定样式参数,并通过一套符合设计师、工程师理解的统一的命名规则,为这些样式参数的定义名称。
原子设计理论提出者 Brad Frost (布拉德 · 弗罗斯特)在《Atomic Design》中提到:原子设计理论从原子(Atoms)、分子(Molecules)、组织(Organisms)、模板(Templates)、页面(Pages)、标准流程(Patterns)再到更完善的设计体系(Design Systems),这一切都是为了产品设计、研发效率和一致性提供帮助。同时,它们也是传达设计原则、构成产品独特气质的基石。Design Token 就是原子级的最基础的构成要素。
根据北美顶级 SaaS 企业的开源设计系统 Saleforce Lightning Design System 的解释,Design Token 是设计系统中的可视化原子,是设计属性的命名实体,使用它们代替具体编码值(如颜色的 16 进制、间距的像素值等),以便于维护一套可扩展且一致性的设计系统。
可以说,Token 就是最底层的原子,本质上就是找到了组件、属性和代码之间的对应关系,统一了设计样式和前端语言,使组件和设计系统可以被快速管理。
Design Token 的优势
基于上述关于 Design Token 的基础解释,可以将 Design Token 的好处可总结为:
- 设计语义-更易理解
- 设计方案-更加一致
- 主题皮肤-一键替换
- 设计变更-高效维护
- 设计成果-精准还原
1. 设计语义-更易理解
每一个组件的基础元素都可以用 Token 进行语义化的命名,帮助设计师和开发建立统一的描述语言。例如#91d5ff 这个色值按照传统的设计规范命名的方式,它可能叫 Blue-3。在实际应用的时候,设计师和开发并不能直接通过 Blue-3 来理解这个颜色到底是用在什么具体场景当中。而当我们通过 Token 语义的方式让它达到组件级别的精度时,它会叫:color-primary-brand-light-disable,不同的设计师和开发就能迅速的理解这个颜色应用在什么具体场景当中。
2. 设计方案-更加一致
当使用组件库实际运用到项目当中时,我们有时候会有不同设计师合作产出一个项目的情况。对于一些不熟悉设计规范或新加入的设计师来说,就会困惑,当使用二级文本色的时候,究竟是用 Gray2、还是 Gray3、Gray4。而这个时候,我们定义一个 Token 名称叫:color-text-secondary,这个 Token 嵌套的颜色是 :Gray3,这样我们设计师在使用的时候,只需要选择 color-text-secondary 这个 Token 变量即可,能选择的颜色就是唯一的,这就能在一定程度上确保不同设计师在同一个场景当中的设计稿保持高度一致性。
3. 主题皮肤-一键替换
主题皮肤的替换可以用在两个维度,一是浅色模式和暗色模式的替换,二是不同品牌色之间的替换。我们可以将不同主题的同一个场景下的颜色使用同一个 Token 命名,例如变量名都叫:color-primary-brand-light-default,蓝色皮肤下对应的值为:#165DFF;红色皮肤对应的值为:#F53F3F。然后通过插件面板的一键操作即可完美切换。同时这种切换模式也可以带入 tokn.josn 代码(后面会具体讲如何输出 json 文件交付开发)中,与开发进行同步。
4. 设计变更 高效维护
还是上面的例子,当我们的二级文字颜色 color-text-secondary 需要进行变更,从 Gray-600 变为 Gray-500。如果没有"color-text-secondary"这个 Token,我们可能需要手动去选中所有用了 Gray-600 的二级文字的图层,一个一个地将它们改为 Gray-500,而当我们有了"color-text-secondary"这么一个 Token 时,我们只需要将 color-text-secondary 的值一键从 Gray-600 变为 Gray-500 便可以完成产品全局的颜色变更。进而设计师可以将 token.json 代码(后面会具体讲如何输出 json 文件交付开发)同步更新给开发 ,开发直接一键替换,线上的界面就能半自动地迅速应用到变更后的色值。
5. 设计成果-精准还原
设计稿能否被开发精准还原,这几乎是每一个设计师在实际项目中会遇到的问题。我们在进行设计验收的时候,即便花了很多时间进行走查,在表格上列举了很多细节问题,但最终的还原效果并不能得到保障。甚至在一些时候会感觉做验收比重新做一遍设计稿还要费劲「emo」,有的时候甚至会直接按 F12 在网页上改代码给开发提示「狗头」。
例如,在常规不使用 Token 的情况下,开发同学使用的是硬代码的模式,代码编辑器无法判断这个颜色是否正确,如果开发不小心输错了一位数,就很可能导致线上运行时候的不一致。而使用了 Token 之后,开发只需要输入这个场景的 Token 名称的前缀,代码编辑器便会自动化地提示有哪几个颜色供选择就可以了,如果不正确,代码编辑器还会给出报错提示,开发同学可以在写代码的过程中完成基础的检验工作,这样一来,设计师的成果便能够一定程度上的精准还原,设计师验收的工作量也会小很多。
在设计系统中应用 Design Token
上面讲了这么多理论,接下来开始实战,准备好~
1. 提炼 Token 组成元素
Design Token 是构成设计语言的基本构建块,是设计系统中最核心、最基础的影响视觉风格的元素。根据 Figma Tokens 插件默认提供的面板中,可以将分别以下组成元素:
Color 颜色、Shadow 投影、Typography 字体样式、Size 尺寸、Space 间距、Border Radius 描边圆角、Border Width 描边宽度、Opacity 透明度等
2. 定义 Token 命名规则
关于 Token 的命名规则,不同的团队有不同的定义方式,但其本质都是为了提高产品的一致性和工作效率。因此在对 Token 命名规则进行分类整理时,设计需要与开发同事达成一致,以确保能够更好地落地。
在制定自己产品的 Token 命名规则前,带大家看一下大厂的 Design Token 都是怎么命名的
腾讯文档 Token 变量表:https://mp.weixin.qq.com/s/sRRPlsxaUZj7220PLoFiRw
腾讯 TDesign 开源设计系统 Token:https://github.com/Tencent/tdesign-common/blob/develop/style/web/theme/_light.less
:root, :root[theme-mode="light"] { // 文字 & 图标 颜色 --td-font-white-1: rgba(255, 255, 255, 100%); --td-font-white-2: rgba(255, 255, 255, 55%); --td-font-white-3: rgba(255, 255, 255, 35%); --td-font-white-4: rgba(255, 255, 255, 22%); --td-font-gray-1: rgba(0, 0, 0, 90%); --td-font-gray-2: rgba(0, 0, 0, 60%); --td-font-gray-3: rgba(0, 0, 0, 40%); --td-font-gray-4: rgba(0, 0, 0, 26%); // 基础颜色 --td-brand-color: var(--td-brand-color-8); // 色彩-品牌-可操作 --td-warning-color: var(--td-warning-color-5); // 色彩-功能-警告 --td-error-color: var(--td-error-color-6); // 色彩-功能-失败 --td-success-color: var(--td-success-color-5); // 色彩-功能-成功 // 基础颜色的扩展 用于 hover / 聚焦 / 禁用 / 点击 等状态 --td-brand-color-hover: var(--td-brand-color-7); // hover 态 --td-brand-color-focus: var(--td-brand-color-2); // focus 态,包括鼠标和键盘 --td-brand-color-active: var(--td-brand-color-9); // 点击态 --td-brand-color-disabled: var(--td-brand-color-3); // 禁用态 --td-brand-color-light: var(--td-brand-color-1); // 浅色的选中态 // 警告色扩展 --td-warning-color-hover: var(--td-warning-color-4); --td-warning-color-focus: var(--td-warning-color-2); --td-warning-color-active: var(--td-warning-color-6); --td-warning-color-disabled: var(--td-warning-color-3); --td-warning-color-light: var(--td-warning-color-1); // 失败/错误色扩展 --td-error-color-hover: var(--td-error-color-5); --td-error-color-focus: var(--td-error-color-2); --td-error-color-active: var(--td-error-color-7); --td-error-color-disabled: var(--td-error-color-3); --td-error-color-light: var(--td-error-color-1); // 成功色扩展 --td-success-color-hover: var(--td-success-color-4); --td-success-color-focus: var(--td-success-color-2); --td-success-color-active: var(--td-success-color-6); --td-success-color-disabled: var(--td-success-color-3); --td-success-color-light: var(--td-success-color-1); // 遮罩 --td-mask-active: rgba(0, 0, 0, 60%); // 遮罩-弹出 --td-mask-disabled: rgba(255, 255, 255, 60%); // 遮罩-禁用 // 文本颜色 --td-text-color-primary: var(--td-font-gray-1); // 色彩-文字-主要 --td-text-color-secondary: var(--td-font-gray-2); // 色彩-文字-次要 --td-text-color-placeholder: var(--td-font-gray-3); // 色彩-文字-占位符/说明 --td-text-color-disabled: var(--td-font-gray-4); // 色彩-文字-禁用 --td-text-color-anti: #fff; // 色彩-文字-反色 --td-text-color-brand: var(--td-brand-color-8); // 色彩-文字-品牌 --td-text-color-link: var(--td-brand-color-8); // 色彩-文字-链接 // 分割线 --td-border-level-1-color: var(--td-gray-color-3); --td-component-stroke: var(--td-gray-color-3); // 边框 --td-border-level-2-color: var(--td-gray-color-4); --td-component-border: var(--td-gray-color-4); // 内投影 用于弹窗类组件(气泡确认框 / 全局提示 / 消息通知)的内描边 --td-shadow-inset-top: inset 0 .5px 0 #dcdcdc; --td-shadow-inset-right: inset .5px 0 0 #dcdcdc; --td-shadow-inset-bottom: inset 0 -.5px 0 #dcdcdc; --td-shadow-inset-left: inset -.5px 0 0 #dcdcdc; // table 特定阴影 --td-table-shadow-color: rgba(0, 0, 0, 8%); // 滚动条颜色 --td-scrollbar-color: rgba(0, 0, 0, 10%); }
Element-Plus:https://element-plus.org/zh-CN/
--el-bg-color: #ffffff; --el-bg-color-page: #ffffff; --el-bg-color-overlay: #ffffff; --el-text-color-primary: #303133; --el-text-color-regular: #606266; --el-text-color-secondary: #909399; --el-text-color-placeholder: #a8abb2; --el-text-color-disabled: #c0c4cc; --el-border-color: #dcdfe6; --el-border-color-light: #e4e7ed; --el-border-color-lighter: #ebeef5; --el-border-color-extra-light: #f2f6fc; --el-border-color-dark: #d4d7de; --el-border-color-darker: #cdd0d6;
Ant Design:https://ant.design/components/overview-cn/
Html { --ant-primary-color: #1890ff; --ant-primary-color-hover: #40a9ff; --ant-primary-color-active: #096dd9; --ant-primary-color-outline: rgba(24, 144, 255, .2); --ant-primary-1: #e6f7ff; --ant-primary-2: #bae7ff; --ant-primary-3: #91d5ff; --ant-primary-4: #69c0ff; --ant-primary-5: #40a9ff; --ant-primary-6: #1890ff; --ant-primary-7: #096dd9; --ant-primary-color-deprecated-PURe: ; --ant-primary-color-deprecated-l-35: #cbe6ff; --ant-primary-color-deprecated-l-20: #7ec1ff; --ant-primary-color-deprecated-t-20: #46a6ff; --ant-primary-color-deprecated-t-50: #8cc8ff; --ant-primary-color-deprecated-f-12: rgba(24, 144, 255, .12); --ant-primary-color-active-deprecated-f-30: rgba(230, 247, 255, .3); --ant-primary-color-active-deprecated-d-02: #dcf4ff;
以上截取的部分 Token 基本是在 Github 上开源社区能找到相关的代码。如果我们想要找一个非开源的设计系统的 Token 怎么找呢?
这里以飞书为例,个人觉得飞书整体的配色非常舒适,想要研究一下其中的 Token 是怎么制定的。
首先打开飞书网页,按 F12,选中任意元素,便可在"样式"中找到飞书产品所有的 Token 是如何命名,以及可以分析研究其中的色彩运用规律。
飞书 Token:www.feishu.cn
--bg-base: var(--N100); --bg-base-raw: var(--N100-raw); --bg-body: var(--N00); --bg-body-raw: var(--N00-raw); --bg-body-overlay: var(--N50); --bg-body-overlay-raw: var(--N50-raw); --bg-content-base: #f8f9fa; --bg-content-base-raw: 248,249,250; --bg-filler: var(--N200); --bg-filler-raw: var(--N200-raw); --bg-float: var(--N00); --bg-float-raw: var(--N00-raw); --bg-float-base: var(--N100); --bg-float-base-raw: var(--N100-raw); --bg-float-overlay: var(--N50); --bg-float-overlay-raw: var(--N50-raw); --bg-float-push: rgba(var(--N00-raw),0.8); --bg-mask: rgba(0,0,0,0.4); --bg-mask-raw: 0,0,0;
Token 命名规则总结
通过上面的大厂 Token 参考我们可以分析出一些普适性的规则:
1. 单词之间用"-"分隔;
2. Token 前缀可自定义添加自己产品的简称,例如:"–el-xx"、"–ant-xx"、"–td-xx";
3. Token 可以套 Token,例如:–td-brand-color-hover: var(–td-brand-color-7);
3. 整理 Design Token 资产表
分析完各个大厂的 Token 规则之后,接下来正式开始对自己产品的 Design Token 开始建设,首先便是整理一份 Design Token 资产表,可以用文档、表格等形式整理。
这里以 TDesign 为例,需要包含 3 列:Token、Value、Describe。这份 Token 资产表整理好之后,可以在设计团队内部进行评审,通过之后再与开发进行对齐。
来源: https://tdesign.tencent.com/design/color
通过工具创建 Token 并联动设计文件
以上主要讲的是在思维层面 Design Token 是怎么推导的,接下来重点讲一下怎么借助一些实用的工具将 Design Token 实现自动/半自动化的落地。
这里主要推荐的工具是 Figma Tokens 插件,它是一款基于 Figma 的插件,相对于 Figma 右侧面板原生自带的样式外,能够实现多层级的 Token 管理,同时插件内容能够与 Figma 设计文件实现实时联动。
1. 安装并运行插件
插件安装地址:https://www.figma.com/community/plugin/843461159747178978/Figma-Tokens
安装完成后,在 Figma 文件中打开 Figma Tokens 插件面板,并点击"Get started",开始创建。
2. 创建 Token 变量
在 Color 分类处点击"+"号,将之前整理的 Design Token 资产表里的内容一个一个录入进插件当中。如何实现 Token "套娃"呢?例如我们需要创建一个"–td-brand-color",值为"–td-brand-color-8",只需要在 Color 值的输入框输入"{–td-brand-color-8}"或"$–td-brand-color-8",这里通过和开发沟通,推荐使用"{ }"大括号的形式进行赋值。全部 Token 创建完成之后,点击"Create Styles"便可将插件中的样式生成到 Figma 右侧的样式面板中。同时,插件中的修改也能够与样式进行实时同步。
3. 通过 JSON 代码快捷导入 Token
上面的方法是需要根据 Token 对照表,通过手动的方式一个一个录入 Token,如果团队的设计师有一点代码功底,或者前端同学能够提前介入进来,直接根据 Token 对照表写一份 JSON 文件,那么也可以直接通过复制 JSON 文件里面对应到代码粘贴到 Figma Tokens 的插件当中,能够直接读取代码生成 Token 样式,并联动 Figma 文件。
4. 导入 Figma 文件中已有的样式
除了使用 Figma Tokens 插件一个一个创建样式以外,插件还支持从我们的 Figma 文件中已经有样式导入,我们也可以点击"Import",再勾选"Color"、"Text"、"Shadows"一键导入文件中的样式并生成 Token。
向研发交付 Design Token
1. 输出 Token.json 代码文件
点击顶部"JSON",再点击"Export",即可将插件面板的创建的 Token 导出为一个 token.json 文件,将 json 文件交付给开发,开发便可使用。若开发不知道如何使用,可以分享这个 Figma Tokens 作者发布在 Github 上的代码稍加学习,便知道如何使用了。
github 地址: https://github.com/six7/figma-tokens-example-tailwindcss
2. 如何更新 Token
当之前定义好的 Design Token 需要增删改时,插件官方推荐的更新同步方式主要有 JSON、 http://JSONBin.io 、URL、GitHub 等几种方式,具体可查阅官方文档: https://docs.tokens.studio/sync/sync 。由于后面集中同步方式涉及到一些小门槛,这里简单介绍第一种最为通俗的更新方式就是直接通过更新 JSON 文件,可以在企业 IM 中和研发创建一个共享空间,每次 Token 有更新只需要将导出的 JSON 文件替换原有的文件即可,开发再应用新的 JSON 文件,便可实现高效便捷的更新 Token。
使用 Design Token 在产品中一键换肤
在一些 To B SaaS 产品当中,产品的主色可能会跟随客户公司的品牌色进行调整。使用 Design Token 便能够便捷高效地实现一键换肤。
1. 首先我们会定义一个"global"基础主题,在这里将所有后面不同皮肤的颜色都写入进来;
2. 在"blue"和"red"主题皮肤下,品牌色命名都为:"tr-color-primary-brand-light-default",但是他们两个皮肤的值不同,一个是 global 中的"{–color-blue-light-6}",一个是 global 中的"{–color-red-light-6}";
3. 在蓝色皮肤下将"blue"勾选,切换至红色皮肤,只需要勾选"red",即可实现文件内的所有变量全局替换,同时 Figma 右侧的样式也能实时联动。
结语
近几年,越来越多的团队开始搭建自己公司产品的设计系统 Design System 赋能到具体产品中落地。我所在的团队也在建设一套适用于自己公司业务的设计系统,在推动设计系统落地时,便运用了 Design Token 进行落地,极大提高了公司设计和研发团队的协作效率。Design Token 给 Design System 带来了新的方式和新的可能,未来希望能够不断扩大 Design Token 的应用价值,赋能到更多的业务和产品当中,让设计系统的应用变得更便捷、更高效。
作者:设计师波波 Bobby He,深耕 B 端体验设计