把行高設為 1 時常出現在行數只有一行時,為了方便排版,避免上下的空白不符合自己想要的高度,特別是容器有指定高度時會使用的方法。例如按鈕、標籤等等。
網頁中的 line-height 是什麼?
在 W3C 裡有明確的定義:
All elements have a 'line-height' property that, in principle, gives the total height of a line of text. Space is added above and below the text of the line to arrive at that line height.
例如把行高設為 1.5,字體大小為 16px,那麼行高則為 16px * 1.2 = 24px
,把 24px-16px=8px
之後再將 8px
切成一半分配到字的上面與下面,又稱為 half-leading。可以參考下圖:
灰色的方塊就是行高,也就是被稱作 half-leading 的部分。W3C 裡面定義的 half-leading 容易跟一般排版印刷的搞混,一般排版印刷裡講的 leading 通常指的是 baseline(下圖的紅線)到下一行的 baseline 的距離。
為什麼不建議設為 1 ?
雖然把 line-height
設定成 1 很簡單,但我覺得這個假設是建立在「文字就只會有一行」的前提上。
然而事實上卻不一定如此,有些人螢幕小可能塞不下那麼多字;有人可能使用習慣上會把文字放很大;有些文字可能來自於使用者輸入,這些情況下原本假定是一行的文字也可能會換行,如果再把行高設成 1,那麼文字就會擠在一團難以閱讀。
另外一種情況是翻譯,有些文字翻譯過後可能會變得更長,如果在實作時是直接寫死 height
反而有可能導致跑版,兩行文字直接超越容器高度。
text-overflow
設為 ellipsis
可能有人會想,既然要保證為一行的話,也可以加入 text-overflow 確保文字超出時用 …
取代。視情況來看這可能是一個方法,但我最近的體悟是這會因為語系而有不同效果。
舉例來說,日文是一個膠著語,句型會取決於語尾的變化,所以時常最重要的部分都在句子的後面,加上 ellipsis
之後就變成超級容易截掉最重要的資訊。
- 私はイケメンです 我是帥哥
- 私はイケメンではありません 我不是帥哥
如果剛好文字截在で,那麼就變成了
- 私はイケメンで…
到底是帥哥還不是帥哥呢?請讓我知道
解決方法
最簡單解決方式就是盡量不要先行假設文字只會有一行,在設計 UI 時也儘可能讓文字有更多表現空間。另外一個方法就是讓行高成為高度的一部分,容器的高度是取決於文字行高而不是直接寫死 height
。
就是因為高度對不起來或跑版才會把 line-height 設成 1 啊!
的確,說起來簡單,但最關鍵的問題還是在於 half-leading 會包含在容器的上下,然而大部分的情況下我們只想要保留文字與文字中間的 half-leading 而已。
我們可以利用 CSS 來抵銷 half-leading 所帶來的高度改變。CSS 中有一個非常好用的屬性 1lh
,雖然是相對比較新的單位,但已經支援現代瀏覽器。
用偽元素把多出來的部分用負 margin 抵銷,至於計算方式我們可以用 (1em - 1lh) / 2
來得到 half-leading 的值是什麼。
.btn {
...
line-height: 2;
&::before {
display: block;
content: "";
width: 0;
height: 0;
margin-top: calc((1em - 1lh) / 2);
}
&::after {
display: block;
content: "";
width: 0;
height: 0;
margin-bottom: calc((1em - 1lh) / 2);
}
}
效果會像這樣,儘管 line-height
是 2,我們也成功把上下的 half-leading 消除了!
另外一個方法是仍在草案的 text-box-trim
屬性,目前只有 Safari Preview 才支援,他的效果就是把上下的 half-leading 給去掉。Github 上面的圖非常生動地展示了它的效果:
這樣一來就不用再煩惱 line-height 造成的高度問題了!雖然等到各個瀏覽器廠商實作還要一段時間,甚至也有可能一直停留在草案沒有下文,但至少可以期待一下。
結論
雖然這篇文章是在反思 line-height 跟 text-overflow 的用法,不過在大部分的情況下其實蠻好用而且蠻夠用的,本文試著提出另外一種思考方式,希望可以給讀者帶來一些新想法。