1.寫在前面
兩個多周的時間沒有寫文章了,手好癢好癢,趁著公司在裝修,從上週末到本週都在家辦公,同時公司的專案並不緊急,於是抽著時間梳理了一下CSS中關於行高line-height
的理解,今天釋出出來,大家準備好了嗎?
2.基本概念
2.1行高的定義與圖解
行高
,顧名思義指的就是一行文字的高度。按照定義來解釋,就是兩行文字之間基線之間的距離。那麼問題來了,什麼是基線呢?大家回想下我們剛開始學習漢語拼音的時候,使用四線格本子的四條線,其中倒數第二條線就是基線,如果你說,抱歉,我已經全部還給老師了,沒有任何印象。呵呵,別急呢,我已經給大家準備好了,請看下面的這副圖,其中,a、c、e、x、z
等字母的底邊線(倒數第二根線)就是我們說的基線。
瞭解完基線的定義後,我們接著來聊行高line-height
。上面我們說過,行高就是兩條基線的之間的距離,如下圖所示。
大家是不是已經?了,大家耐著性子仔細看下,其實挺好理解的:
- 兩條紅線之間的距離就是
行高(line-height)
。 - 上一行的底線和下一行的頂線之間的距離就是
行距
,業界的共識是:行距=行高-em-box(暫時理解為font-size的大小),因此,用CSS語言來解釋行距就是: 行距=line-height-font-size。 - 同一行頂線和底線之間的距離就是
font-size
。 - 行距的一半就是
半行距
。
結合上面圖和文字描述,其實可以很容易搞清楚行高、行距、半行距、font-size
的意思。大家一定要弄清楚這些定義,因為,下文中的內容和這些定義有關。
2.2 內容區、行內框、行框、包含框
所謂一圖勝千言:
內容區:內容區域可以近似理解為FireFox/IE瀏覽器下文字選中帶背景的區域,在上圖中,深灰色背景區域就是內容區域。
行內框:每一個行內元素都會生成一個行內框,高度等於font-size
,當我們設定line-height
的時候,行內框的高度保持不變,改變的是行距的高度。
行框:指本行的一個虛擬的矩形框,由本行中的行內框組成。當有多行內容的時候,每一行都有自己的的一個行框。
包含框: 包裹著上述三種box的box,暈了,直接看圖吧,上面黃顏色的框就是包含框。
3.深入理解line-height
3.1 line-height的各類屬性值
line-height的預設值是normal,同時還支援數值、百分比值、長度值、繼承。請看下面的表格:
值 | 描述 |
---|---|
normal | 預設。設定合理的行間距。 |
number | 設定數字,此數字會與當前的字型尺寸相乘來設定行間距,即number為當前font-size的倍數。 |
length | 設定固定的行間距。 |
% | 基於當前字型尺寸的百分比行間距。 |
inherit | 規定應該從父元素繼承 line-height 屬性的值。 |
- normal
大家在使用line-height
的時候,設定為該值很少,為什麼呢?因為normal是一個與font-family
有著密切聯絡的變數值。例如:
div{
line-height: normal;
font-family: 'microsoft yahei';
}
複製程式碼
和
div{
line-height: normal;
font-family: 'simsun';
}
複製程式碼
這兩段程式碼在不同瀏覽器中測試資料如下:
字型 | Chrome | Firefox | IE |
---|---|---|---|
微軟雅黑 | 1.32 | 1.321 | 1.32 |
宋體 | 1.141 | 1.142 | 1.141 |
從上面的表格中可以看到,指定字型後,在不同瀏覽器中line-height
的解析值基本是一樣的。然而,不同的瀏覽器使用的預設字型不一樣,並且不同的作業系統使用的預設字型也是不一樣的。因此,我們在實際開發的時候,都需要對行高line-height
進行重置操作。
-
inherit
字面意思是繼承,即繼承父元素
line-height
的值,父元素是多少,當前節點的line-height
就是多少,如果當前節點的子節點不設定任何的line-height
,子節點的line-height
也是這個值。 -
length
也就是帶單位的值,比如
line-height: 21px
和line-height: 1.5em
等。如果當前的font-size
為14px,則line-height
計算後的值為1.5*14px=21px
。 -
number
例如,
line-height: 1.5
,最終的計算值是和當前的font-size
相乘後的值,比如font-size
為14px,則line-height
計算值是1.5*14px=21px
。 -
%
例如,當前
font-size
為16px,line-height
為120%,則計算後的行高為16*120%=19.2px
。
不知道大家發現沒有,line-height:1.5
、line-height: 150%
以及line-height: 150%
這三種用法計算的結果 是一樣的,最終計算的行高都是根據font-size
來計算的。是不是它們可以相互替代呢?其實不然,實際上,line-height:1.5
和另外兩個的繼承細節有些區別,我們直接看例子吧。
body{
font-size: 14px;
line-height: 1.5;
}
body{
font-size: 16px;
line-height: 150%;
}
body{
font-size: 14px;
line-height: 1.5em;
}
複製程式碼
對於<body>
元素而言,上面三種方式計算後的的行高都是21px,但是,如果body
下還有子元素,例如:
<body>
<h3>這是標題</h3>
<p>這是內容</p>
</body>
複製程式碼
h3, p{
margin: 0;
}
h3{
font-size: 32px;
}
p{
font-size: 20px;
}
複製程式碼
最終結果是line-height: 150%
和line-height: 1.5em
的最終表現是兩行文字重疊到了一起,如下圖:
而設定了line-height:1.5
的最終表現是兩行文字沒有重疊,排版良好,效果如下圖:
設定line-height: 150%
和line-height: 1.5em
後,子元素繼承的是計算後的值,即21px,而不是繼承150%和1.5em,所以<h3>
和<p>
的行高都是21px,而<h3>
的font-size是32px,則根據上面的公式計算出來的半行距是-5.5px
,因此,兩行文字發生了重疊。
不同屬性下的line-height
最終的計算方式比較如下。
設定方式 | line-height | 計算後的line-height | 子元素繼承的line-height |
---|---|---|---|
inherit | 父元素的line-height值 | 不用計算 | 父元素的line-height值 |
length | 20px | 不用計算 | 20px |
% | 150% | 自身font-size (14px) * 150% = 21px | 繼承父元素計算後的line-height值 21px,而不是150% |
normal | 假如為1.2 | 自身font-size (16px) * 1.2 = 19.2px | 繼承1.2,line-height = 自身font-size(32px) * 1.2 = 38.4px |
純數字 | 1.5 | 自身font-size (14px) * 1.5 = 21px | 繼承1.5,line-height = 自身font-size(32px) * 1.5 = 48px |
所以,在實際開發中, 我們一般設定行高的值為 `純數字是最推薦的方式,因為其會隨著對應的 font-size 而縮放,排版效果良好。
3.2 line-height的"大值特性"
現在,請大家仔細閱讀下面的程式碼:
<div class="box">
<span>這是內容...</span>
</div>
複製程式碼
.box{
line-height: 50px;
}
.box span{
line-height: 10px;
}
複製程式碼
和
.box{
line-height: 10px;
}
.box span{
line-height: 50px;
}
複製程式碼
丟擲問題:請問div
的高度是多少?直接上正確答案:都是50px。請看圖
感覺說不通啊,那麼請看解釋吧。
首先,我們要始終記著,內聯元素前面有一個看不見的"幽靈空白節點",因此,上面的html程式碼可以等價為:
<div class="box">
幽靈空白節點<span>這是內容...</span>
</div>
複製程式碼
所以,當.box
元素設定line-height:50px
的時候,"幽靈空白節點"高度為50px,而當.box
元素設定line-height: 20px
的時候,span
元素的高度變成了50px,而又因為行框盒子是由高度最高的那個內聯盒子
決定的,所以.box
元素的高度永遠是最大的那個line-height
的原因,根據張鑫旭老師的總結,這可以稱為line-height
的大值特性,不知道這樣解釋大家清楚了沒有呢?
3.3 line-height與內聯元素"垂直居中"
- 行高讓單行文字"垂直居中"
不知道你是否和我一樣,在剛開始寫CSS的時候,控制單行文字垂直居中的時候,設定line-height
和height
的值一樣就可以實現文字垂直居中的效果,即:
.title{
height: 50px;
line-height: 50px
}
複製程式碼
其實,這裡只需要保留line-height
這個屬性就可以了,完全沒有任何必要設定height
的大小。
<div style="height: 50px; background-color: #cd0000; color: #fff">
<span style="line-height: 50px">元素元素元素</span>
</div>
複製程式碼
因此,流傳比較廣的"設定line-height
和height
的值一樣就可以實現文字垂直居中效果", 應該修改為:把line-height設定為您需要的box的大小可以實現單行文字的垂直居中。
- 行高讓多行文字“垂直居中”
多行文字垂直居中效果需要藉助line-height
的好朋友的幫助才能實現,程式碼如下:
<div class="box">
<div class="content">基於行高是實現的多行文字垂直居中...我發現文字很短,於是隨便寫了一點文字湊個數..</div>
</div>
複製程式碼
.box{
line-height: 120px;
background-color: #cd0000;
color: #fff;
}
.content{
display: inline-block;
line-height: 20px;
margin: 0 20px;
vertical-align: middle;
}
複製程式碼
效果圖如下所示:
實現的原理如下:
- 多行文字使用一個標籤包裹,同時設定
display: inline-block
,保持了內聯元素的特性,使元素具有單行效果,該設定使元素形成了一個非常關鍵的"行框盒子",而每一個行框盒子都會附帶一個"幽靈空白節點"(寬度為0,但是表現和普通字元相同)。而我們設定了外層的line-height: 120px
,因此,.content
內容"幽靈空白節點"的line-height
也將是120px; - 內聯元素預設是基線對齊的,通過設定
vertical-align:middle
可以實現我們想要的"垂直居中"效果。
3.4 真的是"垂直居中"嗎
不知道大家有沒有留意上文中的單行文字和多行文字的垂直居中都加了引號,難道還不是真正的垂直居中?沒錯,line-height
實現的垂直居中效果只是近似的垂直居中
。為什麼是"近似"?我們拿一個例子說明問題:
<p>微軟雅黑</p>
複製程式碼
p{
font-size: 80px;
line-height: 120px;
background-color: #cd0000;
color: #fff;
font-family: "Microsoft YaHei";
}
複製程式碼
在瀏覽器中(windows系統)的效果如下:
大家看到沒有,這些文字的位置明顯偏下。因為,有些字型的位置偏下,比如"微軟雅黑",在平時我們使用的過程中,字型大小基本在16~18px之間,雖然下沉,但是也就是1px的偏差,我們的肉眼根本察覺不到。因此,使用line-height
實現的"垂直居中"並不是絕對的垂直居中。
同理,使用line-height
和vertical-align
實現的多行文字垂直居中也不是絕對的垂直居中,在上文中多行文字垂直居中的例子中,我們可以明顯的看到字型位置偏下。
其實,不居中並不是line-height
導致的,而是他的好基友vertical-align
造成的,我們會在vertical-align
文章中詳細闡述,敬請期待。
4. 最後
關於line-height
的介紹就到這裡了,平時我們應該多思考,多總結,才會有新的體會。以後我的最新文章都會第一時間更新在公眾號<前端Talkking>裡面,歡迎大家關注。
以上就是本文的全部內容,感謝閱讀,如果有表述不正確的地方,歡迎留言指正!?
ps:這兩天是一年一度的高考,想想自己的高考差不多過去了10年了,而現在自己好像沒有什麼成就,想想好慚愧,努力吧,少年!!!
參考
- 張鑫旭《CSS世界》
- [學習筆記] css中的line-height
遇見了,不妨關注下我的微信公眾號「前端Talkking」