深入行高 - line-height和inline元素的排版

上一篇中提到自己 debug 時(shí)遇到一個(gè) css 知識(shí)盲點(diǎn):行高和字體的關(guān)系。隨后查了相關(guān)資料官份,在這里梳理下這個(gè)知識(shí),最后解釋下產(chǎn)生這個(gè)現(xiàn)象的原因。

現(xiàn)象

一般我們要讓文字在容器中產(chǎn)生垂直居中的效果肥惭,會(huì)把容器高度和行高設(shè)置成一樣,來達(dá)到這個(gè)效果(代碼紊搪,效果圖如下)蜜葱。

<div style="height:32px; line-height:32px; border:1px solid black;">
  <span>Test<span>
</div>
ih-pic1.png

但是當(dāng)容器的字體大小和文字的字體大小不一致的時(shí)候,字體就無法居中了(代碼耀石,效果圖如下)牵囤。

<div style="height:32px; line-height:32px; border:1px solid black; font-size:42px">
  <span style="font-size:20px;">Test<span>
</div>
ih-pic2.png

原理概述:行內(nèi)元素如何排版

在解釋上述現(xiàn)象之前,我們先來看下行內(nèi)元素(inline-element)在頁面上是如何排版的滞伟。我們先假設(shè)頁面上沒有任何我們添加的 css揭鳞,每個(gè)行內(nèi)元素會(huì)占據(jù)一定的矩形空間,我們稱之為行內(nèi)框(inline-box)梆奈,如下圖和代碼:

<div style="border:1px solid black; color:white;">
  <span>span</span> <em>em</em> <strong>I am very very very very very very strong</strong>
</div>
ih-pic3.png

span em strong 都是行內(nèi)元素野崇,背景顏色標(biāo)出了它們行內(nèi)框所占的空間(這里只是為了圖示方便,用顏色標(biāo)示了行內(nèi)框占據(jù)的大致空間亩钟,因?yàn)?css 中并沒有給行內(nèi)元素的行內(nèi)框設(shè)置顏色的屬性)乓梨。而如果沒有用行內(nèi)元素包裹的文字呢?瀏覽器會(huì)給文字生成一個(gè)匿名的行內(nèi)框清酥,如下圖ih-pic3.png 中用綠色框框出來的所示扶镀。

<div style="border:1px solid black; color:gray;">
  anonymous <span>span</span> <em>em</em>
</div>
ih-pic4.png

上面兩個(gè)例子字體都是統(tǒng)一大小的,如果每個(gè)行內(nèi)元素字體不一樣大小呢焰轻?每個(gè)行內(nèi)框會(huì)根據(jù)各自的 vertical-algin 在垂直方向上對齊臭觉,我們先看下示例(示例中每個(gè)行內(nèi)元素的 vertical-algin 都設(shè)置成一樣,但是每個(gè)元素的 vertical-algin 也可以各自不同,這里我就省略了各自不同的例子):

<style>
  span { font-size: 32px; }
  em { font-size: 20px; }
  strong { font-size: 16px; }
  .vertical-align-wrapper * {
    vertical-align: top; /* 對應(yīng)的是圖ih-pic5.png */
    /* vertical-align: middle; 對應(yīng)的是圖ih-pic6.png*/
    /* vertical-align: baseline; 對應(yīng)的是圖ih-pic7.png*/
    /* vertical-align: bottom; 對應(yīng)的是圖ih-pic8.png*/
  }
</style>
<div class="vertical-align-wrapper" style="border:1px solid black; color:gray;">
  anonymous <span>span</span> <em>em</em> <strong>I am very very very very very very strong</strong>
</div>
ih-pic5.png
ih-pic6.png
ih-pic7.png
ih-pic8.png

如果一行中的行內(nèi)元素字體大小和 verticial-align 各不相同蝠筑,那么整個(gè)一行占據(jù)空間是如何算的呢忆肾?這一行的高度最高處由垂直方向上行內(nèi)框最高的元素決定,最低處由垂直方向上行內(nèi)框最低的元素決定(代碼菱肖,圖如下):

<style>
  span { font-size: 30px; vertical-align: top; }
  em {  font-size: 30px; vertical-align: top; }
  strong {  font-size: 30px; vertical-align: top; }
</style>
<div style="border:1px solid black; color:gray; vertical-align: bottom;">
  anonymous <span>span</span> <em>em</em> <strong>I am very very strong</strong>
</div>
ih-pic9.png

圖ih-pic9.png 中黃色框表示的就是整行占據(jù)的空間客冈,我們稱之為行框(line-box)。再給一個(gè)帶上下標(biāo)的示例看看是如何計(jì)算行框占據(jù)的空間(還是黃色框占據(jù)的空間表示行框):

<div style="border:1px solid black; color:gray; vertical-align: bottom;">
  anonymous <span>span</span><sup>sup</sup> <em>em</em><sub>sub</sub> <strong>I am very very strong</strong>
</div>
ih-pic10.png

所以行內(nèi)元素字體大小決定了字的大小稳强,每個(gè)行內(nèi)元素占據(jù)的空間又由行內(nèi)框(inline-box)決定场仲,最后一整行如果只有行內(nèi)元素,則所占據(jù)的空間就是行框(line-box)決定的退疫,高度亦是行框的高度渠缕。如果文字很長折成了多行,那么每行都是按照以上規(guī)則生成多個(gè)行框褒繁,并在垂直方向上以容器內(nèi)部邊界的左上角開始向下排列:

ih-pic11.png

接下來我們就要看下 line-height 是怎么影響元素的了亦鳞。剛剛我們提到一個(gè)行內(nèi)元素占據(jù)的空間叫行內(nèi)框,那么行內(nèi)框的高度是如何決定的呢棒坏?就是 css 屬性行高(line-height)決定燕差,瀏覽器通常全局的默認(rèn)行高是 normal,約等于字體的1.2倍坝冕。譬如一個(gè)行內(nèi)元素的字體是 12px徒探,那么行高就是 12 x 1.2 = 14.4(px)。而行高和字體間的距離差距我們叫做 leading(中文可以叫做行間距喂窟,不過網(wǎng)頁上的行間距和傳統(tǒng)印刷業(yè)的行間距代表的地方不同测暗,這里就不描述其歷史和不一樣的地方了)。瀏覽器會(huì)把 leading 除以二磨澡,平均放到字體的上面和下面碗啄,這兩塊平均空間的距離叫做 half-leading,如下圖(圖中為了演示明顯稳摄,字體大小設(shè)為 16px稚字,行高設(shè)為 32px):

ih-pic12.png

如果 line-height 小于字體大小,那么行內(nèi)框的高度就會(huì)向字體的中心線收縮秩命,字體將會(huì)溢出行高尉共,如下圖(圖中為了演示明顯褒傅,字體大小設(shè)為 32px弃锐,行高設(shè)為 20px):

ih-pic13.png

行內(nèi)框的高度會(huì)影響行框的高度,我們假設(shè)極端情況每行只有一個(gè)行內(nèi)元素殿托,那么每行行框(line-box)的高度就是這個(gè)元素行內(nèi)框(inline-box)的高度霹菊,讓我們看看多行情況下行高(line-height)大于字體和小于字體產(chǎn)生的效果,溢出行高的字體將在多行垂直方向疊加:

ih-pic14.png

最后我們說下如果手工設(shè)置了元素的 line-height,將如何影響元素:

  1. 行內(nèi)元素設(shè)置 line-height 等于指定了行內(nèi)框的高度旋廷。
  2. 沒有行內(nèi)元素包裹的文字所生成的匿名行內(nèi)框的高度是繼承自它的父容器鸠按。
  3. 塊級(jí)元素包裹了一系列行內(nèi)元素,這些行內(nèi)元素自己沒有設(shè)置 line-height饶碘,那么給塊級(jí)元素設(shè)置 line-height 等于給被包裹的行內(nèi)元素指定了最小行內(nèi)框的高度目尖。

現(xiàn)象產(chǎn)生原因分析

一般情況:

<div style="height:32px; line-height:32px; border:1px solid black;">
  <span>Test<span>
</div>

div 設(shè)置的 line-height:32px 給 span 限定了行內(nèi)框的最小高度,而 span 的默認(rèn)行高和字體都沒有超過 32px扎运,所以 span 的行內(nèi)框高度就是 32px瑟曲,又因?yàn)?half-leading 平均分配的原理,那么字體就會(huì)在行內(nèi)框中居中豪治,如果一行字行內(nèi)框高度相同洞拨,那么整行文字的行框高度就是 32px,最后 div 的高度又設(shè)置了 32px负拟,所以最后文字看起來是垂直居中的烦衣。(其實(shí)如果以此例來說 div 不設(shè)置高度也沒有問題,因?yàn)?div 高度就是按內(nèi)部元素高度而撐開的)

異常情況:

<div style="height:32px; line-height:32px; border:1px solid black; font-size:42px">
  <span style="font-size:20px;">Test<span>
</div>

雖然看上去 div 只有一個(gè)子元素 span掩浙,但是從規(guī)范上我得知花吟,這種情況下有一個(gè)寬度無限小的匿名行內(nèi)框存在。如果在 div 上設(shè)置了字體 42px厨姚,那么這個(gè)匿名行內(nèi)框的字體就變成了 42px示辈,且 div 的 line-height 只能指定匿名行內(nèi)框的最小高度,當(dāng)匿名行內(nèi)框的字體大于 32px 時(shí)遣蚀,這個(gè)匿名行內(nèi)框的高度就變大超過了 32px矾麻,最后導(dǎo)致整行的行框高度超過 32px。而 span 的行內(nèi)框和字體雖然都沒有超過 32px 芭梯,但是它的 baseline 需要在水平方下沉和這個(gè)匿名行內(nèi)框?qū)R险耀,但是 div 的高度限制成了 32px,最后看上去 span 就不在垂直居中的方向上了玖喘。

參考資料

  1. https://www.slideshare.net/maxdesign/line-height
  2. https://www.w3.org/TR/REC-CSS2/visuren.html#inline-formatting
  3. http://www.zhangxinxu.com/wordpress/2009/11/css%E8%A1%8C%E9%AB%98line-height%E7%9A%84%E4%B8%80%E4%BA%9B%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E5%8F%8A%E5%BA%94%E7%94%A8/
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甩牺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子累奈,更是在濱河造成了極大的恐慌贬派,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澎媒,死亡現(xiàn)場離奇詭異搞乏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)戒努,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門请敦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事侍筛∮┰恚” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵匣椰,是天一觀的道長裆熙。 經(jīng)常有香客問我,道長禽笑,這世上最難降的妖魔是什么弛车? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮蒲每,結(jié)果婚禮上纷跛,老公的妹妹穿的比我還像新娘。我一直安慰自己邀杏,他們只是感情好贫奠,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著望蜡,像睡著了一般唤崭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脖律,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天谢肾,我揣著相機(jī)與錄音,去河邊找鬼小泉。 笑死芦疏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的微姊。 我是一名探鬼主播酸茴,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兢交!你這毒婦竟也來了薪捍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對情侶失蹤配喳,失蹤者是張志新(化名)和其女友劉穎酪穿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晴裹,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡被济,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了息拜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溉潭。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡净响,死狀恐怖少欺,靈堂內(nèi)的尸體忽然破棺而出喳瓣,到底是詐尸還是另有隱情,我是刑警寧澤赞别,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布畏陕,位于F島的核電站,受9級(jí)特大地震影響仿滔,放射性物質(zhì)發(fā)生泄漏惠毁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一崎页、第九天 我趴在偏房一處隱蔽的房頂上張望鞠绰。 院中可真熱鬧,春花似錦飒焦、人聲如沸蜈膨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翁巍。三九已至,卻和暖如春休雌,著一層夾襖步出監(jiān)牢的瞬間灶壶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工杈曲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驰凛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓担扑,卻偏偏與公主長得像洒嗤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子魁亦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 參考文章:深入了解CSS的line-height屬性Vertical-Align: 你需要知道的所有事【譯】Ver...
    若邪Y閱讀 3,452評(píng)論 1 6
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案渔隶? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,761評(píng)論 1 92
  • 前言 總括: 本文通過實(shí)例講解CSS中最大的難點(diǎn)之一,行內(nèi)元素的布局洁奈,主要是挖掘line-height和verti...
    秦至閱讀 1,921評(píng)論 0 1
  • 1.vertical-align 默認(rèn)值:baseline 即設(shè)置該屬性的元素的基線(baseline)與行框的基...
    softbone閱讀 964評(píng)論 0 0
  • 行高: 兩行文字“基線”之間的垂直距離 基線并不是漢字的下端沿间唉,而是英文字母"x"的下端沿 行距: 一行“底線”至...
    lmmy123閱讀 1,767評(píng)論 0 2