基于约束的设计系统

设计系统是用户 web 界面的基础,在我 15 年的设计和工程工作中,我花费了大量的时间来思考、讨论、搭建和维护设计系统。尤其是后来我承担了 staff+ 等级的工程工作后,我要确保我的团队都能从统一的技术角度看问题。这对设计师和前端工程师来说尤为重要,因为他们虽然属于不同领域, 但工作内容会出现重叠的情况。

设计和前端工程的相似性导致了一个有趣的现象:两者的术语和关注领域有重叠,如颜色、排版、布局、状态置换等,但这些领域在设计和前端工程里各有不同的考虑因素和执行方法。大家可能有过(或听过)关于这些差异的对话或争论:设计师不理解为什么工程师不会构建非常简单的界面元素;工程师不理解为什么设计师会觉得布局的像素与设计规范里的像素差异太大会是个问题。这些争论的起因往往都是设计师和工程师其实是两个不同的领域,这似乎有些不可思议:这两个领域难道不应该使用同样的语言吗?

最糟糕的情况下,设计和工程之间的这种不一致会在团队层面造成巨大挑战:界面设计和代码库的现实会变得非常不同,导致团队不断被迫在质量(与设计保持一致)和效率之间做选择(没有人喜欢作这种选择),而在明确决定之前,大家会暂停工作来解决各项分歧,导致功能或整个产品耽搁过长时间,又或者,时间非常宽裕,但没有人愿意分歧,它变成了技术和设计债务。

在这一系列挑战下,合作数字产品的团队开始把设计系统的成功执行作为必备条件。当设计师和工程师目标一致时,就能创造出内在一致的、可重复的、灵活的、比任何一方单独设计都优秀的产品。

我用这个假设引出本文的核心。本文整合了我多年来在设计系统领域对工程师和设计师的指导和培训的经验。为避免过于深入特定领域,本文重理论和应用,轻实施。虽然必然会涉及到一些实施细节,但本文的初衷不是为设计系统的具体实施提供参考。我的目的是提出一个严格的概念基础,在这个基础上构建或分析网络上有效的设计系统。

接下来,我们进入正题。


什么是设计系统?

首先,设计系统不是一个新概念,尽管它在当前的科技行业非常有热度。几千年来,人类一直在有意图地设计,规范设计的系统也存在了差不多同样长的时间。因此,设计系统的从业人员有大量的历史资料可以借鉴。

但究竟什么是设计系统? Figma 的设计系统网站上的这篇文章摘录给了一个很好的定义(为保持一致,我把他们的术语“设计模式”换成“设计系统”)。

[......] 设计系统是一种正式的记录常见设计问题的解决方案的方式。设计系统是一种通用资源,可以调整最佳实践,描述优秀设计的元素,最重要的是,它提供资源库,方便其他人重复地使用这些解决方案。既然前人已经造了车,我们何苦要重新发明轮子呢?
现代设计师通过设计系统让新设计师迅速掌握品牌的细微差别,获得跨越时间和人员的集体智慧,为团队提供统一语言,减少浪费在“重复工作”上的时间,同时确保终端用户无论借助何种媒介或通过任何设计师都能获得同样的体验。

获得跨越时间和人群的集体智慧至关重要。设计系统并不是纯粹为了定义规则而存在的。这些规则(或解决方案)必须是精辟的且是集体解决问题的成果,而且只要定义这些问题的参数保持不变,这些解决方案就应当能被其他人再次使用。

以上对设计系统的描述为本文提供了一个很好的理论出发点,但设计系统在实践中是如何体现的呢?这个答案在不同的研究领域(城市规划、建筑、平面设计、计算机编程等)各有不同,我通常把数字产品的设计系统定义为包含:

1. 品牌设计规范(高等级的排版、调色、布局感觉等)

2. 一个可重复使用的组件库——即通过实际应用(离散的字体元素、图标、互动元素等)传达该品牌设计的组件集合

3. 一个模块化的代码库,将这些组件变成终端用户的现实

因此,设计系统不仅定义了一个团队的外观和感觉,还定义了用户与一个团队的数字产品和服务的互动方式。换句话说:设计系统直接影响了用户界面的实现。


用户界面的作用和面临的挑战

当用户界面(以及支持它的设计系统)能够消除用户和其目标之间的矛盾时,才是最有效的。目标反过来必须为设计系统的实施提供依据。我们在考虑目标时,一定要注意不要把手段和目的混淆:

人们不愿意使用你开发的软件。
他们想减肥,想开怀大笑,想娱乐,想变得更聪明,想和爱的人在一起,想按时回家,想有充足的睡眠,想吃好东西,想快乐。
一个产品能让人们获得多好的体验,就有多好。
— @shl

任何由设计者和开发者精心设计的界面都必须以用户需求为出发点。为了使一个界面能够成功地实现这一目标,它必须是:

  • 一致的(建立信任,让用户熟悉产品)
  • 可预测的(设定预期并减少认知障碍)
  • 高效的(尊重最宝贵的资源——时间)
  • 可访问的(让尽可能多的人可以使用该界面)

因此,设计系统的工作就是规定一个团队应该如何创建一致的、可预测的、高效的和可访问的用户界面。

这些属性对用户至关重要,但人们往往忽视了它们对负责建立这些界面的设计师和工程师来说同样重要。如果一个设计系统对设计师和工程师来说不是一致的、可预测的、高效的和可访问的,那么就很难指望它制作优秀的用户界面。

这就是我们面临的挑战,尤其是对于正在成长中的团队来说:随着在这个问题空间中工作的人数的增加以及问题空间本身的扩大,解决一致性、可预测性、效率和可访问性变得更加困难。这源于系统的规模和熵之间的关系,或者,简单来说是系统走向无序的趋势。为控制我们的系统,我们要关注对系统进行定义的参数。这就是约束重要的原因。


接受约束

有效的设计会优化约束。这适用于任何设计:建筑、工程、软件、产品设计,等等。这些约束不仅有用,而且关键:一个美丽的建筑如果没有参照构造运动和气候变化等约束来设计,就会倒塌;产品如果没有针对网络的各种约束来设计,就永远无法积累起关键的用户群。此外,一个没有足够约束的设计系统很快会发展到一种无序的混乱局面,尤其在有了更多贡献者、遇到更多设计问题后。

根据约束来构建的系统更注意可维护性和可学习性,从而使其更易学习,更稳定,且迭代更快。

下面我们举一个简单的例子来证明。


实践中的约束:间隔尺度

你在设计一个版面时(无论是作为设计师还是工程师),一定无数次考虑过这个问题:“这个应该离那个多少像素?”有多少次你凭着自己的直觉,尝试各种数字的变化,直到“看起来正确”?有多少次你不得不向设计师要上限,或要求工程师把边距从 13 像素改为 14 像素?

现在,你是不是经常遇到团队中的其他人在设计或编码时通过调整布局让其“看起来正确”,但他们使用的测量方法与你用的方法的不同?怎么判断哪个方法是正确的?而且,当你下次需要为某些东西留出空间时,你还会记得具体像素值吗?另外,新员工怎么知道该用哪个值?不知道的话岂不是很累?你难道不愿意用这些时间去做更重要的事情吗?

你肯定愿意!所以接下来我们来谈一谈间距比例。

间距比例的逻辑是这样的:任何给定的布局应该其中的离散元素之间使用特定的、一致的增量空间。假设你需要让一个输入端与它的标签保持一定的距离,你需要从间距比例中选一个值。假设你需要设计一个网格布局,那么每列和每行之间的沟槽也是用间距比例的一个值来确定大小的。你的用户界面的每一个元素, 除了极少数的例外,都应该与其他元素保持一定的间距,这个间距是在你的间距比例上找到的。

间距比例及其在组件和页面布局中的应用

间距比例在本质上是“模块化”的(与连续范围相反),间距比例中的每一步都比前一步大一定比例。间距比例可以是 2 的幂数,例如(4px、8px、16px、32px、 64px...),或者更复杂的东西。重要的是决定一个对团队有意义的比例,把这个比例纳入你的设计工具和代码库,然后坚持使用。

间距比例是基于约束的设计模式的例子之一,它在多个层面上解决问题。它们有效地减少了“神奇数字”的使用(凭感觉选择的或其他不合逻辑来源的独特数值),并大大减少了设计时间,也为整个界面和产品创造了和谐的、有节奏的、一致的布局。一旦设计师和工程师熟悉了这些比例,他们甚至不需要其他设计师设定上限(或由工程师确定精确的数值)——重复的间隔变得一目了然,从而加速了构思、实施和迭代。对于新手设计师和工程师而言,间距比例还可以减少学习和内化设计系统的时间。

特别是当在设计工具和代码库中得到很好实施时,间距比例将布局设计推向一个更加参数化和更少特异性的过程。重要的是,这并不意味着使用间距比例或基于约束的设计系统会扼杀创造力。毕竟,首先还是要由设计师和工程师来定义间距比例和其他对约束的反应,而在约束下解决问题本身就是一种高度创造性的行为。


将约束投入实践

尺度和其他参数值不仅可以而且应该用于间距比例,还可以用于网格、字体大小、 颜色调色板等等。通过限制设计系统中的值和变化,我们可以减少设计师或工程师对设计系统必须了解的知识的数量。这在很大程度上加强了一致性和可预测性。在一个设计系统中,什么属性应该被映射到约束中,这个决定在不同的团队中可能是不同的。我给大家举一个例子,下面是我在 Ellii 负责开发的设计系统中定义的参数,以及每个参数被定义的值:

  • 断点 (4)
  • 颜色(约 50 种,但常规使用中只用其中的四分之一)。
  • 阴影 (4)
  • 字体大小 (9)
  • 字母间距 (5)
  • 线路高度 (4)
  • 边界辐射 (3)
  • 间隔增量 (8)

仅凭这 8 个参数和(除了我们的色块)每个参数的一小套数值,我们就能够设计出一个严格限制但又无比灵活的设计系统。这些核心参数在很大程度上定义了所有最终出现在屏幕上的东西的实现,从细微的排版细节到整个页面布局和复杂的互动组件。这也使我们的设计师和工程师能够在一个广泛但定义明确的概念沙盒中快速设计、构建和迭代。

在一个团队的设计工具和代码库中实现这类约束的方法几乎可以和设计系统本身的组成一样多。然而,鉴于近年来人们对设计系统的兴趣大增,大众有了越来越多的选择。例如,Figma 的设计标记插件为设计师提供了在他们的线框、模型和原型中编码和使用设计系统约束的程序化方法。作为一名前端工程师,自从 Brent Jackson 的样式系统库在 2017 年首次出现,我就一直喜欢使用它;Theme UI 是另一个不错的选择。对于那些不在 React 中工作的人来说,基于约束的设计系统可以很容易地在普通的 CSS 中实现 - Tailwind, 一个流行的功能性 CSS 库,甚至面向设计系统内的使用

然而,在构建一个设计系统时,仅仅实施约束是不够的。设计系统通常不是静态的——团队的需求随着时间的推移而变化,新的问题空间被打开,有时这些空间需要解决在实施设计系统时从未考虑过的问题。因此,与约束打交道并不是一件“设定好了就不去管它”的事情。我们必须学会如何随着时间的推移有效地管理约束。


表面积、体积和系统的复杂性

在一个更简单的世界里,支撑一个设计系统的参数和价值将被决定一次,然后永远使用。当然,现实很少是如此简单的。

必须谨慎对待设计系统的迭代。有时,对一个设计系统进行看似简单的调整就足够了——这里增加一个颜色,那里增加一个字体大小。然而,即使是最简单的改变,也有可能给设计系统带来指数级的复杂性。为了帮助人们理解其中的原因,我发现在几何学的世界里走一段简短的弯路是有帮助的(很简单,我保证)。

首先,快速回顾一下术语:在描述三维物体时,我们可以用“表面积”一词来描述物体外部的大小(例如,一个纸板箱外部面板的综合大小),用“体积”一词来描述物体所包含的空间大小(例如,同一个纸板箱内的空间量)。当三维物体增长时,它们的表面积和体积之间的关系发生了一些有趣的变化,它们不会以同样的速度增长。

以立方体为例,随着立方体大小的增加,其体积的增长速度比表面积的增长速度快。准确地说,在给定的边长 𝑥,其体积为 𝑥³,而表面积为 6(𝑥²)。
——计算机程序的体积和表面积

立方体的表面积和体积之间的变化率的差异


我们用调色板举例,比如,最简单的调色板,黑色和白色。在我们的调色板中只有黑色和白色,我们只能创造两种不同的颜色组合。

如果我们增加第三种颜色,例如红色,会发生什么?我们现在可以创造多少种颜色组合?

通过在我们的双色调色板上增加一种颜色,我们可用的颜色组合数量增加了两倍。 想象一下,增加一种颜色如何不仅在调色板本身产生变化,而且在与其他设计系统参数(如字体大小)的可能组合数量上产生变化。这种增长关系听起来很熟悉,不是吗?

一个设计系统的不同参数,以及这些参数可以采取的价值,可以被认为是设计系统的表面积:它们共同勾勒出设计系统可以产生的可能性空间。每当表面积增加——多一种颜色,多一种字体大小——设计系统的体积,或者说所有这些参数和属性作为一个整体可以相互作用的综合方式,就会以更快的速度增加。

伴随着这种不断增长的组合空间,我们还需要考虑设计系统的变化所带来的质量上的复杂性。回到在调色板上增加一种颜色的例子,我们马上想到了一些问题。

  • 为什么需要这种颜色?
  • 这种颜色应该被命名为什么?
  • 这种颜色是为了承载语义吗?如果是的话,是什么?
  • 这种颜色应该用在哪里?哪些地方不应该使用它?
  • 在我们的设计系统中,这种颜色能与哪些其他颜色搭配?它不应该与哪些颜色结合?
  • 在我们的设计系统中,它能否无障碍地与其他颜色一起使用?
  • 除了颜色本身之外,是否还需要颜色的变化?

随着设计系统数量的增加,其复杂性也随之增加。任何设计系统中的复杂性都是不可避免的,在某种程度上,它甚至可以作为一种表达多种可能性的手段而流行。然而,设计和工程中过多的复杂性不可避免地会导致无序——不一致、 不可预测、低效和不可访问,这些正是设计系统首先要避免的东西。

这并不是说设计系统不应该随着时间的推移而迭代,也不是说在设计系统形成过程中对它的约束应该是不可改变的。所有存在足够长的时间的设计系统都需要修改。重点是,系统的约束及其影响必须是设计系统从业人员长期关注的问题,这些约束的改变必须是经过深思熟虑的。


总结:设计系统和连贯性

设计系统的核心是一个统一的工具。通过有效的实施,设计系统将一个团队的意图与它的产品相协调,在这些产品的制造者(也就是团队的设计师和工程师)之间形成连贯性。

然而,优秀的设计系统并不局限于设计和工程人员;它们对于产生整个团队可以依赖的最终结果至关重要,从质量保证和管理到通信和商业。因此,保持设计系统的稳定性不是一件小事,而且这项任务必须得到适当的时间和关注才行。

特别是当为设计系统做贡献和使用设计系统的人越来越多的时候,有效的沟通变得至关重要。设计师和工程师必须定期进行建设性的对话,那些领导设计系统的开发和维护的人必须与整个团队有紧密的反馈回路。如果不是这样的话,设计系统陷入混乱的风险就会增加。这可能会给整个团队带来灾难性的影响。

根据我的经验,防止这种无序现象增长的最好方法是确保设计系统从业人员定期和主动地会面,当然,要始终牢记系统的约束。有些团队可能大到足以支持一个专门的、跨职能的设计系统团队;在这种情况下,定期开会和紧密的沟通循环有望成为定局。在较小的团队中,设计系统可能是由设计师和工程师建立和维护的, 他们的大部分时间都是直接在产品上工作,预约定期会议(两周一次或每月一次)来关注设计系统是非常必要的。在各种规模的团队中,保持异步沟通渠道对所有人开放也很重要(例如 Slack 上的公共设计系统频道),努力消除设计师和工程师之间的孤岛,并建立有效的跨职能团队。

同样值得一提的是,优秀的设计系统需要优秀的文档。即使有许多经过深思熟虑的约束,我们也必须记住,新员工可能并不熟悉设计系统的原理,也不熟悉你的特定设计系统所处的问题空间。(当然,你可以随时把这篇文章发给那些不熟悉设计系统的人,但同事你也应该把你的特定系统记录好)。

在积极主动和知情沟通的基础上进行构建和维护,设计系统会成为一个非常强大的团队资产。它们能够创造出一致的、可预测的、有效的和可访问的用户界面, 从而使终端用户更接近他们的目标。如果实施得当,它们还可以做到这一点:一个团队的设计师和工程师,如果本身不是设计系统的贡献者,那么通过简单地重复使用设计系统产生的人工制品(其组件),就可以节省大量的时间,从而可以专注于建造传说中的火箭船,而不必担心制造自己的螺母、螺栓和燃料来源。

以上是我的一些经验,希望这篇文章能帮助大家。


感谢

这篇文章借鉴了过去 8 年中我在多个公司的设计系统的成功案例,以及我在此前几年中作为设计师兼工程师的经验。我也从 Adam Morse 和 Brent Jackson 的学习中受益匪浅,所以我一定要感谢他们多年来的启发、指导和非常优秀的示例。另外,还要感谢 Adam 对本文的建议。



原文作者:Cole Peters
原文链接:https://www.colepeters.dev/posts/an-introduction-to-constraint-based-design-systems


推荐阅读
相关专栏
前端与跨平台
90 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。