iT邦幫忙

2022 iThome 鐵人賽

DAY 4
4

間距、間距、間距!

情境

在討論今天的主題之前,我們先來看看下面這張圖:

第一張圖的情境,有可能是在介面上我們試圖要做一些不可逆的操作,例如你要去刪除某篇文章,系統跳出一個確認訊息避免你誤按,跟你 double check 你要做的行為是否是你確定要這麼做的。

第二章圖的情境,有可能是我們要在某個部落格上發表文章,或是編輯文章,做完所有編輯行為之後,要將內容送出。

類似像這樣的介面我們生活中隨處可見。當然,在我們的工作上,你也有很高的機率會需要設計這樣的介面。

你能看見多遠的未來呢?

今天我們要討論的主題是,像這樣的介面共同的部分,是在下面有一顆按鈕讓我們做確認。那這顆按鈕有什麼特別的呢?

當然,我們今天如果只有一顆按鈕,確實是沒有什麼特別的。但一般來說像這樣的介面,通常會有兩顆按鈕,我選一張圖來舉例:

.actions {
  display: flex;
}
<div class="actions">
  <button class="button outlined">Cancel</button>
  <button class="button contained">Confirm</button>
</div>

我們花了一番功夫,終於讓按鈕可以做水平排版了之後,喘完一口氣,卻發現上面這兩顆按鈕黏太近了,要怎麼辦呢?

黏太近的話當然就是把他隔開嘛,這還用說?但仔細想想,「你要用什麼方法把他隔開呢?」。

這就是我們今天要討論的主題了。

我們來看看今天能夠想到幾種能達到同樣效果的方法,並且一起來分析他的優劣吧~

用 inline-style 加上外距

inline-style 是一個很直覺得做法,看到哪裡缺什麼就在那裡加什麼:

<div class="actions">
  <button class="button outlined">Cancel</button>
  <button class="button contained" style="margin-left: 12px">Confirm</button>
</div>

當然這樣的做法是一定會奏效的,只是我們會需要來討論這樣到底有什麼隱憂。
其中一個部分是,使用 inline-style 雖然方便,但是他卻沒有辦法實作如 media-query、hover 等特殊 CSS 效果。

所以如果今天的設計稿是,在寬螢幕的呈現方式需要兩顆 button 距離為 20px,變成手機版窄螢幕的時候需要調整為 12px。那這樣 inline-style 就會有點困擾,我們可能就會需要多寫一段 javascript 來做適應性的調整。

另一個隱憂是樣式權重的問題:

// 最左邊的權重最高,最右邊的權重最低
!important > inline-style > ID > Class/psuedo-class(偽類)/attribute(屬性選擇器) > Element

如果我們程式碼到處都用了 inline-style,那很有可能你會發現寫了某段 CSS 之後卻沒有出現效果,因為偷偷在某個你已經忘記了的地方有權重更高的 CSS 壓過你目前的 CSS。這時候你要回去找這段在做怪的 CSS 時,就會發現很頭大了。有可能他會很難找,也有可能你改了他之後,其他地方的樣式也會被影響到。

用 class 加上外距

那既然上述例子的做法不太推薦,那把 inline-style 拿出來放在 class 裡面如何呢?

.first-button {
  ${buttonStyle}
}

.not-first-button {
  ${buttonStyle}
  margin-left: 12px;
}
<div class="actions">
  <button class="outlined first-button">Cancel</button>
  <button class="contained not-first-button" style="margin-left: 12px">Confirm</button>
</div>

我們在 class 裡面可以寫 media-query,另外 class 的權重也比 inline-style 低,解決了這兩個問題。

但是用這種寫法仍然無法擺脫一個問題,就是感覺有點過於 hard code 了,寫法上不太有彈性。舉例來說,假設還有其他的 button 接續在後面,那是不是每一個 button 都需要加上這個樣式呢?

你需要很小心,不能漏掉一個。如果這段程式碼被修修改改,特別是被不同的人接手修改,那很有可能會被改到漏掉。

<div class="actions">
  <button class="outlined first-button">Cancel</button>
  <button class="contained not-first-button" style="margin-left: 12px">Confirm</button>
  <button class="contained not-first-button" style="margin-left: 12px">Edit</button>
  <button class="contained not-first-button" style="margin-left: 12px">Delete</button>
</div>

用外容器來控制間距

上面兩種方法有剛剛提到的缺點。另外我們再深入一點思考,「外間距是屬於 button 上面的屬性嗎?」

換句話來說,如果 button 沒有帶外間距的樣式,他還是不是一顆完整的 button 呢?答案當然是肯定的。

我們可以這樣理解,button 元件本身其實不需要外間距,會有這個外間距的需要,是因為這裡有一群 button 擠在這裡,所以需要間距把彼此隔開,是因為這個「群體」所以才需要間距,撇開群體不談,button 本身壓根就不需要外間距。

既然我們得出這個結論了,那我們就把間距的控制從 button 裡面大膽的抽出來吧!我們應該把他放在外容器上,就是包覆這個 button 群體的父元素。

[經驗分享]
如果以元件化的角度來看,我們在系統上必定會有這個系統共用的 button 元件,這樣的共用元件會被放在各種地方,不只是我們今天所舉的那兩種情境。那假設這個 button 被放在另外一個情境,但這個情境卻不需要間距,那是不是很尷尬呢?我們還需要特別寫一些 CSS 把這些多餘的樣式拿掉,顯得特別麻煩,可讀性也會降低,今天你自己看得懂,別人來看就不知道你的用意。

所以以上述的狀況來考量的話,我不太建議把跟 button 元件本身無關的間距直接放在 button 上。

使用相鄰兄弟選取器(adjacent-sibling combinator)

如果需要選擇緊接在另一个元素後的元素,而且二者有相同的父元素,可以使用相鄰兄弟選取器(Adjacent sibling selector)。

.button + .button {
  margin-left: 12px;
}

使用頭尾選取器(:first-child)

:first-child 從字面上來解釋的話,就是選到第一個子物件,那我們想要做的事情是,「除了第一個 button 之外,其他後面的 button 都要加上左邊的外間距」。

.actions :not(:first-child) {
  margin-left: 12px;
}

使用 Flexbox 佈局

在做元件的水平、垂直佈局時,Flexbox 是很常用的佈局方法。在處理間距這件事情上面,Flexbox 也提供了很棒的實作,可以直接用 gap 來定義垂直方向及水平方向的間距:

.flex-container {
  display: flex;
  flex-wrap: wrap;
  column-gap: 12px;
  row-gap: 20px;
}

但是在使用 Flexbox gap 會需要特別留意在瀏覽器版本的支援度,Safari 在 14.1 之前是不支援 Flexbox gap 的喔!

加上間距之後就能夠順利把 button 隔開了:

小結

今天我們討論了 button 水平排版的間距,並且討論幾種能達到同樣效果的方法,並且一起來分析他的優劣:

  • 用 inline-style 加上外距
    • 直覺、簡單實現,但無法用 media-query,且 CSS 權重太重
  • 用 class 加上外距
    • 解決前面 inline-style 提到的問題,但寫法不太有彈性,哪裡需要外距就要加在那裡
  • 用外容器來控制間距
    • 分別演示相鄰兄弟選取器、頭尾選取器、Flex 佈局在外容器上達到效果

今天是以 button 水平佈局情境為例來說明間距的處理,但今天討論的內容不限於 button 元件喔!


上一篇
【Day03】間距 - 標題與圖示
下一篇
【Day05】內容長度 - 類別標籤
系列文
防禦性 CSS - 建立「防患未然」的匠人心態30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
Dylan
iT邦新手 1 級 ‧ 2022-09-22 13:14:42

似乎有錯字

類似這樣的介面我們生活中隨處可見

Taiming iT邦研究生 5 級 ‧ 2022-09-22 13:55:02 檢舉

哇!你看得好仔細!感謝提醒!

1
Global Rachel
iT邦新手 3 級 ‧ 2023-06-27 21:19:18

學習了!

我要留言

立即登入留言