教學 | 深入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 做例子:

<style type="text/">
body {font-size:35px;line-height:屬性自帶;}
p {font-size:12px;}
.main {font-size:25px;}
</style>
</head>
<body>
<p>text wolrd<br />second line</p>
<div class="main">this is for main<br />class=main</div>
</body>

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)都會跟著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>
</head>
<body>
<p>text wolrd<br />second line</p>
<div class="main">this is for main<br />class=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,我在這做了一張簡圖給各位參考:

可以看到每個字都有1個inline box包圍,inline boxes再組成line box,line boxes再組成containing box。英文的話是一個單字為一組inline box。

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

而我在一開始提到的文字截斷的問題,就是跟inline boxes、content 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)。

我們先寫一個簡單的CSS+HTML:

<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>
<br /><br />
<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

引用網址:

FACEBOOKs COMMENT():

EVERYBODYs COMMENT:

  • 1
    BoKeam (LV.18) // 2010.09.01 12:54

    謝謝阿木哦,line-height之前我只知道它用來定義行距 :mrgreen:

  • 2
    muki (LV.1145) // 2010.09.01 13:12

    @ BoKeam
    很高興這篇文章能幫助到你,我以前也是只用他來定義行距XDDD

  • 3
    ifenwen (LV.3) // 2010.09.01 13:13

    教学的话 最好给出可视化的效果

  • 4
    tony (LV.18) // 2010.09.01 20:32

    @ifenwen:
    想要別人交的話,最好給出可視化的實體(錢)
    意或是您認為您那都是程式碼的教學比較可視化?

  • 5
    nofx (LV.2) // 2010.09.01 21:03

    @ ifenwen
    MUKI這樣寫的很用心了..難到你要買書送光碟!!! :-?

  • 6
    Lay (LV.8) // 2010.09.01 22:37

    :!: :!: :!:
    好詳細的教學喔 :-P

    感謝摟^^ :wink:

    :arrow: :arrow: :arrow: :arrow: :arrow: :arrow:

    好可愛的圖喔XD :-? :-? :-?

  • 7
    馬諦斯 (LV.37) // 2010.09.01 22:53

    CSS達人, 8)

  • 8
    scorpio (LV.15) // 2010.09.02 12:17

    丫木老師很久沒寫教學了~~~

  • 9
    按摩器 (LV.1) // 2010.09.03 18:09

    谢谢博主分享,学习了

  • 10
    聽.風 (LV.1) // 2010.09.04 02:38

    沒想到line-height也有這麼多學問

  • 11
    scorpio (LV.15) // 2010.09.07 10:42

    line-height還可以用來做單行垂直置中的效果...

  • 12
    uggboot (LV.3) // 2010.09.10 15:50

    一直不明白为什么台湾那边都是繁体字

  • 13
    Alan (LV.4) // 2010.09.18 17:35
  • 14
    米卡 (LV.1) // 2010.11.15 18:56

    很精采的文章!! 但有一處覺得有些怪怪, 可能是我誤解了, 向阿木版大請益... 8-O

    您先前提及 "行高就是基線跟基線之間的距離", 但後面在提box model是怎麼分配他們的自己的高度時, 卻又是以 (line-height 減 font-size)/2, 分配在content area的頂部跟底部, 這是否在呈現上有所不一致? 謝謝!!

  • 15
    muki (LV.1145) // 2010.11.19 16:02

    @米卡
    安安,我思考了一下你的問題,你問的非常的好,讓我也不知道該怎麼回答....
    請再多給我一點時間想想 :oops:

  • 16
    zhkzyth (LV.1) // 2010.11.27 17:25

    阿木老师,那个图全部挂掉了...还有,繁体字让我看得很崩溃,虽然字体可调大调小很给力....

    • muki (LV.1145) // 2010.12.03 20:39

      我這邊看圖是沒有問題的...
      另外,建議你可以裝個簡繁轉換的插件用用

  • 17
    min (LV.1) // 2011.04.08 10:54

    受益良多~thx! :wink:
    圖我看是正常的,應該是大陸那裡有擋住吧?

  • 18
    dodo (LV.2) // 2011.06.21 09:00

    繁體字好美!!歡迎來學繁體字!! :-D

  • 19
    怕冷的企鵝 (LV.3) // 2011.07.08 19:59

    高手...!!!
    看了這篇又長知識了!~~感謝muki解惑!!


  • LEAVE YOUR COMMENT:




      :wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!:


     
    字體大小: 小字型 12px大字型 15px
    ▲ back to top