← 所有文章

修复大多数UI的五个间距决策

当一个界面让人觉得别扭,却说不出问题在哪里时,答案通常是间距。不是配色,也不是字体,而是那些空隙。间距是一套看不见的系统,它告诉眼睛什么属于一起、什么彼此独立、什么最重要;而它失效时悄无声息:没有哪个默认的linter会对13px的空隙报警,也没有哪位评审会写下“节奏坏了”。多年来审视自己和他人的界面之后,我做的几乎每一处间距修正,都落在同样的五个决策之中。 {.answer-block}

TL;DR

  • 确立一套刻度,并拒绝一切不在其上的值。 4、8、16、24、32、48、64。13px的空隙不是设计决策,只是漂移。
  • 组与组之间的间距必须大于组内的间距。 仅这一条格式塔法则,就能替代大多数边框和方框。
  • 给每个容器一个由角色推导出来的内边距(组件16、卡片24、区块32-48),而不是逐条边去目测。
  • 在伸手去拿分隔线之前,先让留白建立层级。 边框,不过是间距放弃之后的样子。
  • 垂直节奏要在文字层面修好:line-height至少1.5,标题下方的间距小于上方的间距。这一层若不成立,它之上的任何调整都救不了整个页面。

1. 先确立刻度,再拒绝一切不在其上的值

选哪些值只是第一个决策中较小的那一半;较大的那一半,是承认确实存在一组值。我用的是4px基准:4、8、16、24、32、48、64,七个值,各配一个令牌。(数据表格、工具栏这类高密度界面有时确实值得加一个12;如果你的界面需要,就把它变成令牌。有罪的是没有名字的值,而不是第八个令牌。)

令牌 用途
xs 4px 行内元素、图标间隙
sm 8px 同一组内的相关项
md 16px 标准组件内边距
lg 24px 卡片内边距、区块内部的间隙
xl 32px 主要区块之间的分隔
2xl 48px 区块的上限、页面级的下限
3xl 64px 首屏主视觉区

具体数字本身,不如那份拒绝重要。随手取的值(13px、7px、22px)会破坏节奏,眼睛能感到那份潦草,却说不出它的名字。我给自己定下的规矩是:每一个间距值,要么来自刻度,要么带着写进文档的理由。实际上,写进文档的例外几乎从不能通过评审,因为“当时看着挺对”正是刻度要防的那种漂移。

刻度还会压缩决策的数量。没有刻度,每一处空隙都是在实现速度下临时做出的新判断;有了刻度,大多数空隙只剩下一个说得通的令牌,设计评审于是可以去争论真正有意思的情形,而不是做算术。

2. 组间距 > 组内距

如果只从这篇文章里带走一句话,那就是这句:组与组之间的空隙,必须明显大于组内部的空隙。 这是格式塔的邻近原则在承重——眼睛会自动地、在语言之前就把相对距离读成关系。

一个表单,如果标签距离输入框8px,而输入框彼此相隔24px,就不需要方框,不需要分隔线,也不需要背景色块:分组不言自明。把这些距离统统压平成16px,同一个表单就变成一团等距排列的行,用户必须靠意识去解析。同样的三个字段,两种排法:

grouped (8 within / 24 between)     flattened (16 everywhere)

Name                                Name
[______________]
                                    [______________]

Email                               Email
[______________]
                                    [______________]

Phone                               Phone
[______________]
                                    [______________]

在左边,每个标签毫无疑问属于它下面的输入框。在右边,中间的每个标签都悬在两个输入框的正中间——邻近原则不再投票,读者只能靠阅读顺序而不是靠眼睛来判断归属。

失败的模式几乎总是“在错误的层级上压缩”:设计师为了在首屏塞进更多内容而收紧组间距,比例随之崩塌;接着,感到分组正在瓦解,他又加上边框来补救。这就引出了第四个决策。不过在那之前,还有一件事:

3. 每个容器只有一个内边距,由角色推导

容器积攒不对称内边距的方式,就像厨房积攒杂物抽屉:这里挪一点好放下按钮,那里改一点为了图标,直到某张卡片上边18px、左边14px,而没人记得为什么。解法是一条恒定的推导规则:容器的内边距由它的角色决定,而不是由它的内容决定。

  • 组件(按钮、输入框、标签片):16px
  • 卡片与成组的内容:24px
  • 区块:32-48px
  • 页面级与首屏主视觉区:48-64px

当内容装不进某个角色的内边距时,是内容对这个容器来说不合适:拆开它、缩短它,或者把容器提升一级。为了迁就一个别扭的子元素而调整内边距,会毁掉所有同级元素的节奏;那份不对称,即便是永远不会开口提起的用户,也会读成一个bug。

4. 留白先于边框

大多数分隔线都是道歉。列表每一行下方的横线、表单每个区块外面的方框、卡片与卡片之间的发丝线——每一根,都是放弃了的间距。边界确实能形成分组(格式塔的共同区域原则是真实存在的),但它是那味药:视觉上喧闹、只做加法、还会层层累积。每多一条边框,眼睛就得多处理一条线。

我的实际顺序是:先试邻近比例(第二个决策)。如果分组仍然分不开,就在描线之前先试背景的变化——一块浅色底不必添线就能造出区域,这是共同区域分组最安静的形态;只要某一组需要的是凝聚力而不是边缘,它总是胜过边框。表格里的斑马条纹,就是这条规则最常见的样子。真正需要硬边缘的区域——表格、可编辑区域、嵌套卡片——才动用边框,而且一旦用了就贯彻到底。一个界面若在这里用留白分组、在那里用边框分组,读起来就像两套设计系统在打架。

我在评审时用的检验方法是:删掉所有不是在标记合法硬边缘(表格、可编辑字段)的边框,然后看还剩下什么。活下来的分组是真的;散掉的那些,是边框一直在替它偿还的间距债务。

5. 在文字层面修好垂直节奏

间距系统是从底部开始死掉的。如果正文的line-height是1.2,区块间距给得再多也救不了页面——段落本身读起来就是挤的,建立在它之上的一切都继承了那份紧绷。底线是:正文16px,line-height 1.5(长文可到1.75),每行长度在65ch左右。 其中有实证依据的是line-height:无障碍指南写下1.5是有原因的,而过紧的行距是网页上最常见的节奏杀手。65ch这个上限则是经验而非法则:长行单独测试时可能表现良好,但视线折回下一行行首会越来越难落准,读者往往在遇到论点之前,先遇到了一堵字墙。

在段落之上,组织其余一切的规则是:标题离它引出的内容,要比离它承接的内容更近。 上方留白大于下方留白,通常是两倍。悬在两个区块正中间的标题,哪一边都不属于;正是那份不对称,把它绑在自己的内容上。同一个标题,两种排法:

bound (before wide / after tight)   floating (equal both sides)

...end of previous section.         ...end of previous section.


Shipping address                    Shipping address
[Street___________]
[City_____________]
                                    [Street___________]
                                    [City_____________]

在左边,标题明显拥有它下面的字段。在右边,它悬在两个区块之间,读者只能按惯例而不是按视觉去分配归属。这又是第二个决策,只不过这次运行在文字栏内部——这正是重点:垂直节奏并不是一门单独的学问,它就是邻近原则在最小尺度上的应用。

审查清单

这五个决策可以压缩成一份评审清单,我拿它检查任何一个界面:

  1. 每一处空隙都在刻度上吗?(把那些异常值查一遍——它们永远是意外。)
  2. 每一处组间空隙,都比那些组内部的空隙更大吗?
  3. 每个容器都只带一个由角色推导出的内边距吗?
  4. 有没有哪条边框,在修好它背后的间距之后就可以删掉?
  5. 文字栏守住自己的节奏了吗——line-height 1.5以上,标题绑定在自己的内容上?

大多数界面会在其中两三条上不及格,而修好它们对观感的改变,超过任何配色或字体的更换。在我自己的iOS应用里,第一条是机械强制的:提交发出之前,评审关卡会在diff里grep原始的内边距数字,凡不是套件令牌的值,都需要一个有名有姓的理由才能活下来。间距是手艺藏身的地方,恰恰因为没人指得出它。

常见问题

设计系统应该采用什么样的间距刻度?

4px基准的刻度——4、8、16、24、32、48、64——几乎覆盖了界面的所有需要。具体数值不如排他性重要:每一处空隙要么来自刻度,要么带着写进文档的理由。随手取的值(7px、13px、22px)会以用户能感到却说不出名字的方式破坏视觉节奏。

不用边框,怎么给UI元素分组?

靠邻近比例:组与组之间的间距,必须明显大于组内部的间距。标签到输入框8px、到下一个标签之前24px,不用任何方框就能把表单分好组。边框留给真正需要硬边缘的区域——表格、可编辑区域——并把背景色的变化作为中间一步优先考虑。

卡片和按钮应该用多大的内边距?

由容器的角色推导:组件(按钮、输入框)约16px,卡片24px,区块32-48px,首屏主视觉区更大。每个容器一个值——如果内容装不进这个角色的内边距,就改内容或把容器提升一级,而不是手工微调每条边。

排版中的垂直节奏是什么?

它是一栏文字自上而下保持一致的间距模式:正文至少16px、line-height 1.5-1.75,每行约65个字符,标题离它引出的内容比离它承接的内容更近。更大的一切都从这一层继承而来——如果段落本身就是挤的,再多的区块间距也修不好这个页面。

相关文章

图标是一套词汇,而非装饰

界面图标像一门语言,人人都认得的词只有十来个。默认配文字标签,一个产品只用一套图标家族,一个动作只对应一个隐喻。

9 分钟阅读

表单法典:每个字段都是一个问题

表单设计有一部法典:单栏布局、可见标签、宽容的输入、能教人修复的错误提示,以及绝不丢弃用户已经填下的内容。这些规则本身,以及每一条存在的理由。

10 分钟阅读

设计哲学:上田文人与减法设计

上田文人在二十年里只做了三款游戏,把一切无助于那一种情感的东西统统删去。这是减法设计,来自那位砍掉椅子的画家。

8 分钟阅读