Design Token在设计和开发中应用(一)

介绍

Design Token是在设计中用来存储和管理设计属性的一种方式,几乎所有视图属性都可以建立对应的Design Token,它最大的特点就是可重用性、可维护性、可扩展性、可读性高,设计师和程序员在设计或开发中都可以复用同一套Design Token。

概念是比较抽象的,以下我举一个我们日常中比较经常实用的例子:颜色Token。

Hard code的方式

这里有一块简单的梯度色板,这一块梯度色板是由16进制的颜色的RGB(A)命名。

首先我们可以直观地看到颜色并复制使用其色值,这种方式也称为hard code,这种方式的设计稿和编码的可维护性是极其差的,并且看着这一堆数字也容易摸不着头脑,可读性也非常差。

而在编码中也是如此。

swift 复制代码
GooseButton(
    action: {},
    label: { Text("Primary Button").foregroundColor(Color(hex: 0xFFFFFF)) }
).background(Color(hex: 0x9747FF)) // extension function

为叙述方便,文中的代码都使用伪代码的方式实现,未必是最佳实践。

Hard code的问题

一旦使用hard code的方式来使用设计资源将会带来非常多的问题。

可维护性差

如果需要在设计稿或者程序中修改某个类型的属性,将会需要在"使用这个属性"的所有地方进行修改,在代码中尚可使用全局搜索的方式来修改,但是在设计稿中将难以进行这种操作。一旦需要修改,将会在评审阶段产生大量分歧和阻力

重复度高

如上面所述,在需修改阶段需要对使用了该属性的地方一个个进行修改,这是一项重复度高且无意义的工作,绝大多数情况下,有很多个控价都使用同样的色值,在修改的时候需要一个个核查,这也增加了工作时间,大大降低了效率。

可读性差

由于设计属性都是使用hard code的方式来使用,阅读起来非常的困难,不知道这个颜色指代的是什么。

复用

一般在项目启动阶段,就算设计师没有交付Design Token到程序员那边,程序员也不明白Design Token的概念,程序员也会想到一个问题:复用代码。而如何复用代码呢?

举个例子,在程序开发中新建一个颜色资源时,需要给这个颜色资源命名,这个名字具体是什么?参考什么命名?这些问题一般会抛给设计师,由设计师去定义,而这个起名的过程,也是Design Token初步建立的过程,一旦名字起好了,双方需要严格按照对应名字取使用资源,否则将会产生分歧或设计稿不还原。

一旦建立了名字和颜色的对应,颜色将被赋予语义化,所有控件取什么颜色将有据可依。在设计或开发中将会非常顺畅,大家的协作幸福感将会提高。

协作幸福感是一个非常重要也是最被大家忽视的东西。试想一下,你是一名设计师,你觉得设计稿的某个色值看起来非常不和谐,你把它换成了更舒服和谐的颜色。在评审阶段由于"工作量大,不改也不影响使用"的原因给否决了,你的内心将会非常受挫,而此前所有的调研和工作将白费。换个角度,你是一名程序员,由于历史原因代码中没有复用颜色资源,设计师提出修改某个控件颜色后,你需要花很多时间去做重复的工作,整理设计资源,并且容易产生漏改错改的问题,看到大量的BUG单你会非常头疼。

大家在沟通过程中产生矛盾时将会降低协作幸福感,甚至直接影响工作幸福感、工作效率,这并不利于身心健康发展,容易产生一系列问题。

要规避这个问题,需要提前定义好Design Token并落地,如刚刚所述,Design Token最简单的使用就是将设计资源语义化并复用,如何进一步去更好地使用呢?

设计资源不仅仅指某一个属性,它很广泛,可以是多个属性的集合,例如:字号、粗细、行高的集合,也可以是圆角的参数。

如何构建Design Token

Color Token

以刚刚的梯度色板为例,我们在设计时经常会使用梯度色板来进行配色,各个色阶也可以对应一个命名,如下所示:

具体如何起名,不同的设计系统有不同的起名方式,上图仅供参考。一旦为梯度色板中的颜色起名,该颜色将赋予语义,我们在查找某个颜色的时候可以直接去通过颜色名字搜索,防止产生大量相近但不完全一样的颜色,导致视觉观感上乱七八糟。

而这一层命名未必需要交付给开发,开发没有必要知道你是取哪个梯度的颜色,开发所需要的信息就是这个颜色是什么意思,给谁用的?因此我们需要往下再延伸。

假设我们取刚刚的颜色为品牌主色调,我们为其命名为primary,命名到达这个阶段之后,我们就能很清楚这个颜色是做什么的

而开发得到这个颜色的命名也足够用于开发了,这也是目前很多项目对于Color Token的用法。

swift 复制代码
struct GooseColorScheme {
    static let primary = Color(UIColor(named: "ref.palette.purple40")!)
}

假设按钮需要使用这个颜色,顶栏也需要使用这个颜色,如果我们需要改按钮的颜色的话,我们需要找到所有按钮,并修改其颜色引用,这非常不友好,我们可以再往下一层。

一旦延伸到component级别,修改某个控件的颜色将变得轻而易举,如果我们需要改悬浮按钮的颜色,直接将component.fab.container的颜色引用修改到目标颜色,不去改变其他控件的颜色即可。这使批量修改控件颜色变得轻而易举。

swift 复制代码
struct GooseColorScheme {
    static let primary = Color(UIColor(named: "ref.palette.purple40")!)
    static let primary2 = Color(UIColor(named: "ref.palette.purple60")!)
    static let fabColor = primary // 只需修改这个的引用即可
}

// UI
FabButton(
    action: {},
    containerColor: GooseColorScheme.fabColor,
    icon: {},
)

而对于控件而言,不同的状态拥有不同的颜色,例如鼠标悬浮状态,点击状态,禁用状态等等。此时我们还可以往下延伸一层。而具体一个Color Token需要有多少层需要根据实际情况来定,并不是层数越多越好,对于简单的设计系统,过多的层数对于工作效率来说反而起反作用。

Typography Token

文本的参数也可以Token化,以下为Material Design You默认的Typography。

不同语言的字体展示会有所不同,英文的Typography放在中文下可能会有些水土不服,这个可以根据项目的具体情况做调整。

其他设计属性

颜色和字体是最常见建立Design Token的属性,而其他设计属性也可以建立Design Token,如圆角弧度,阴影大小等等,只要你想,所有属性都可以复用。但是并不是Design Token越多越好,有很多属性需要定制,此时它不应该被标准化。

Design Token落地

Design Token是一个约束规范,需要设计和开发达成共识并严格按照其规则来实行,一旦有一方没有落地,Design Token的意义将失去了一半,这也是实际项目中非常常见的误区,我们不能只看到眼前的工作内容,项目的有序进行需要大家互相协同。

  • 曾遇到项目的代码为图方便直接以16进制RGBA给颜色命名,而设计有自己的命名规范,这就直接导致在工作中开发跟不上设计进度,设计走查错漏百出。
  • 又或者开发以自己的理解给颜色命名了,相似的颜色都复用这个颜色,设计师在后续走查时发现项目里大多数颜色都是错的。

设计师需要及时建立相应的规范文档并交付给开发。这个交付方式多种多样:

  • 直接给规范文档开发编写代码来同步,缺点是容易遗漏。
  • 可以直接导出类似Json的方式来交付给开发,开发拿到文件再转换成对应的开发资源,可以做到资源同步,并减少遗漏。

如果Design Token通过服务端下发,我们还可以动态下发不同的文件来实现不发版对设计资源热更新。这对于灰度更新、A/B Test或者收集用户意见非常方便。

总结

本文主要介绍了Design Token的概念和用途,Design Token是用于存储和管理设计属性的一种方式,可以实现可重用、可维护、可扩展和可读性高的设计属性。通过使用Design Token,可以实现颜色的复用和语义化,提高设计和开发的协作效率。

在落地过程中设计和开发达成共识是一件非常重要的事情,它不只是某一方的工具,它是推动项目快速迭代,高效维护的关键因素。由于篇幅有限点到为止,而该系列后面的文章主要在于实践,进一步介绍工具的使用和Design Token落地。

相关推荐
周亚鑫6 分钟前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
Justinc.23 分钟前
CSS3新增边框属性(五)
前端·css·css3
neter.asia39 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫39 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
嚣张农民1 小时前
JavaScript中Promise分别有哪些函数?
前端·javascript·面试
光影少年1 小时前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_1 小时前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu10830189111 小时前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾1 小时前
前端基础-html-注册界面
前端·算法·html
Dragon Wu1 小时前
前端 Canvas 绘画 总结
前端