← 所有文章

修好大多數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,七個值,各對應一個token。(資料表格、工具列這類密度高的畫面,有時確實值得多一個12;如果你的介面需要,就把它變成token。有罪的是沒有名字的值,而不是第八個token。)

token 用途
xs 4px 行內元素、圖示之間的空隙
sm 8px 同一群組內彼此相關的項目
md 16px 標準元件內距
lg 24px 卡片內距、區塊內部的空隙
xl 32px 主要區塊之間的分隔
2xl 48px 區塊的上限、頁面層級的下限
3xl 64px 主視覺區塊

比起具體數字,那份拒絕更重要。隨手取的值(13px、7px、22px)會破壞節奏,眼睛感受得到那份草率,卻說不出它叫什麼。我要求自己遵守的規則是:每一個間距值,不是取自級距,就是帶著寫進文件的理由。實務上,寫進文件的例外幾乎撐不過審查,因為「當下看起來剛剛好」正是級距要防的那種偏移。

級距也會把決定的數量壓下來。沒有級距時,每一處空隙都是在實作的速度下臨時做出的新判斷;有了級距,大多數空隙只剩一個說得通的token,設計審查因此可以去爭論真正有趣的情況,而不是做算術。

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應用程式裡,第一條是機械式強制的:commit送出之前,審查關卡會在diff裡grep原始的內距數字,凡不是套件token的值,都得有一個叫得出名字的理由才能留下來。間距是手藝藏身的地方,正因為沒有人指得出來。

常見問題

設計系統應該採用什麼樣的間距級距?

以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 分鐘閱讀

動態語法:動畫何時才配得上它佔用的影格

介面動畫是一門語法很小的語言:四檔時長、兩條緩動規則、一個直白的測試。說不出它為什麼要動,就刪掉。

7 分鐘閱讀

設計哲學:上田文人與減法設計

上田文人在二十年間只做了三款遊戲,把一切無助於那一種情感的東西全部拿掉。這是減法設計,來自那位砍掉椅子的畫家。

8 分鐘閱讀