深入 CSS 之 line-height 應用

前幾天改版後,發現留言的版面,頭像上面的樓層顯示出了點問題,在 IE6、IE7 底下看,會發現文字被截掉(如下圖)。

後來詢問CSS達人:風痕影以及SR之後,發現只要設置line-height就可以了!

於是當下我對 line-height 產生了興趣,想知道為什麼要這麼設定才可以解決字被截斷的困擾,因此上網搜尋了一下,查到了幾篇文章。

在 ISD webteam 這裡有一篇翻譯過後的文章:深入 CSS 行高,雖然標題打「深入」二字,但其實這篇是從淺至深講得很清楚,建議大家可以先看這篇文章,理解 line-height 真正扮演的角色為何。簡報第 81 ~ 83 頁就解決了我上述問題的疑惑,原來是 line-height 跟 font-size 的設定問題,導致 inline box 比 content area 小。

接著跟大家推薦的第二篇文章,是來自鑫空間的css 行高 line-height 的一些深入理解及應用,這裡把許多 line-height 會碰到的問題,還有如何應用都寫得很詳細。大推啊!!!

看完這兩篇之後,讓我對 line-height 又更加認識了。而有時候我閱讀完文章,會有作筆記的習慣,因此我結合了這兩篇寫出了 line-height 心得,另外一點是因為上面兩篇作者都是內地的朋友,在語氣以及專有名詞上,跟我們還是有點出入。我會嘗試用大家所習慣的口吻教導大家 line-height 的知識。也許所學不精、也許未嘗完善,所以看完後如有疑問歡迎提出,謝謝:)

什麼是 line-height

line-height 的中文是「行高」,簡單來說就是兩行文字中間的高度。

行高的高度,是以文字的基線(baseline)為準,小時候有在外面補習英文的朋友,應該都曾經被教導要在格線上寫英文吧,而那條對準英文字母的線就是我們所說的基線(如下圖)。

▼ 行高就是基線跟基線之間的距離

line-height 屬性及作用

line-height,總共有 5 種屬性可供運用,假設有一段 HTML code,p.main的文字大小分別是 12px 以及 25px,就讓我們看一下,使用不同的line-height屬性,行高會如何變化。

<p style="font-size: 12px;"></p>
<div class="main" style="font-size: 25px;"></div>

1. 預設值

寫法為line-height:normal,行高會依照(該元素設定的文字大小 x 1.2)* 的結果作為依據。

▼ 使用line-height:normal為例,行高的最終值如下:

p:12(px) x 1.2 =14.4(px)
.main:25(px) x 1.2=30(px)

* 1.0 ~ 1.2 是瀏覽器給 line-height 的初始值,通常都用 1.2 來計算。

2. 純數字

寫法是line-height:1.8;,行高會依照(該元素設定的文字大小 x 1.8)的結果作計算。
簡單來說,你的數字設定多少,行高就會乘以多少。

▼ 使用line-height:1.8;為例,行高的最終值為:

p:12(px) x 1.8 =21.6(px)
.main:25(px) x 1.8=45(px)

3. 帶單位的值

寫法是line-height:18px;,不管字型大小,你設定行高是 18px,他就是 18px。單位選擇有 em, px, pt …等。

▼ 使用line-height:18px;為例,行高的最終值為:

p:18px
.main:18px

4. 百分比

寫法是line-height:180%;,行高會依照(父元素文字大小 x 180%)的結果作依據。

例如我設定 body 的行高是 180%,那麼所有 body 的子元素(包含 body )都會跟著該設定。那如果 p 的行高另外設成 150% 呢?那就是從 p 以下(包含 p )的子元素都會套用 150% 的設定。

▼ 使用line-height:180%;為例,行高的最終值為:

p:35(px) x 180% = 63(px)
.main:35(px) x 180%= 63(px)

5. 繼承

寫法是 line-height:inherit;,如果加上這段語法,就會繼承該父元素的設定。(因為繼承的寫法跟上述四種都不同,所以我單獨拉出來講)。

關於繼承:請以以下 html 為例
<style type="text/css">
  body {font-size: 35px;line-height: 1.8;}
  p {font-size: 12px;}
  .main {font-size: 25px;line-height: 3;line-height: inherit;}  /*繼承被寫在這裡*/
</style>
<body>
  <p>text wolrd<br />second line</p>
  <div class="main">this is for main</div>
</body>

▼ 設定.main{line-height:inherit},行高的最終值為:

.main(有繼承):25(px) x 1.8= 45(px)
.main(無繼承):25(px) x 3 =75(px)

當有繼承的時候,會是自己的文字大小 x 父元素的行高;反之拿掉繼承,就是自己的文字大小 x 自己的行高。


line-height 跟 box model 的關係

先簡略說明什麼是 box model,我在這做了一張簡圖給各位參考:

每個字都被 1 個 inline box 包住,inline boxes 組成 line box,line boxes 再組成 containing box。英文的話是一個單字為一組 inline box。

接著我們把其中一段話放大,會發現有一個隱形的 box 圍繞著文字,他叫做 content area,他本身是一個隱藏的 box,我們沒辦法對他做任何事情。而這個 box 的高度取決於文字的大小。

而我一開始提到的文字截斷問題,就是因為inline boxescontent area,以及line-height的關係(講了那麼久終於講到重點了…)

設定好行高後, box model 是怎麼分配他們的自己的高度呢?

舉例來說,假設我的行高跟字型大小這麼寫:font-size:12px; line-height:16px; ,可以看出他們的行間距差了 4px,接著 box model 會把這 4px 除以 2,也就是 4(px)/2=2(px),然後把 2 個 2px 分別分配在 content area

的頂部跟底部(如圖)。

也就是說,content area 的高度是 12px,而 inline box 的高度是 16px。當 inline box 高於 content area 的時候,兩邊是相安無事的,因為文字不會被截斷。

但如果,inline box比 content area 小呢!!?

假設我寫成:font-size:16px; line-height:12px; ,而 inline box 的高度會優先以行高最為依據,所以 inline box 高度是 12px。但前面提到 content area 會圍繞著文字,所以文字大小設為 16px,content area 也是 16px。在這種情況下,就會有文字超出 inline box(如圖)。

因為 content area 是隱形的,我們肉眼所能看到的範圍只有 inline box 的藍底區塊。所以當 inline box 比較小的時候,它所包覆的文字會被截斷,我們看到的也只是那塊藍底截斷的文字。

這也就是為什麼,當你發現文字被截斷的時候,可以使用line-height來解決截斷問題。

但最有效的方法,還是在於一開始,設定字型跟行高時就要注意,避免這樣的問題產生。

高度是 line-height 還是 font-size 決定

最後來談談高度吧。我們都知道當 div 有了文字就會自動產生高度。那麼這個高度是由line-height還是font-size決定的呢? (這邊指的不是指定高度 height)。

我們來寫一個簡單的片段:

<style>
  .a {
    font-size: 15px;
    line-height: 0;
    border: 1px solid #ccc;
  }
  .b {
    font-size: 1px;
    line-height: 15px;
    border: 1px solid #ccc;
  }
</style>

<div class="a">大家好,我是阿木</div>
<div class="b">大家好,我是阿木</div>

出來的範例如圖(有興趣的朋友可以把語法copy回去試試看):

在這邊我就不多做解釋了,相信聰明的各位一定看得出來高度到底是由誰決定的:D。

參考文章:
1.css行高line-height的一些深入理解及應用 / 鑫空間 鑫生活
2.[譯] 深入 CSS 行高 / ISD Webteam
(這兩篇真的講得很詳細,再次推薦!!)

3.Box Model – CSS 框框模型 [2*] / 網頁藝術思考
4.CSS3 Text Effects Module / W3C