CSS进阶(7)—— 内联元素的掌管者line-height和vertical-align(上)
在CSS世界中,塊級元素一般負責結構,而內(nèi)聯(lián)元素則負責文字內(nèi)容,而CSS設計的初衷就是面向圖文混合排版,因此內(nèi)聯(lián)元素在CSS世界中有著非常重要的地位。由于本章內(nèi)容較多,因此特分為上下兩章,依舊可以根據(jù)興趣按小標題獲取你所需要的信息。
1.字母x與CSS世界的基線
要了解內(nèi)聯(lián)元素,就不得不提到字母x,正是有了x,內(nèi)聯(lián)元素才確定了自己的基線(baseline),有了baseline之后,才有了line-height和vertical-align。因此在學習后面的內(nèi)容之前,必須要了解一個概念:
字母x的下邊緣線就是內(nèi)聯(lián)元素的基線(baseline)!
既然x那么重要,因此CSS還給了它一個特殊的稱呼叫x-height。顧名思義,x-height指的就是小寫字母x的高度,那么這個x-height有沒有用呢?答案是肯定的,如vertical-align:middle的定義就是baseline往上1/2*x-height的位置,因此我們看到的vertical-align:middle在font-size較大的時候會顯得不是特別“垂直居中”,因為不是每個字/字母的高度都和字母x相同,或者說,大部分都是不相同的。
由于vertical-align:middle需要基于x-height進行運算,那么CSS干脆給這個x-height一個名份,進一步衍生出了相對尺寸單位ex,1ex = x-height,因此這個單位會隨著font屬性的變化而變化,非常的不穩(wěn)定,所以不太適合用來限定元素的尺寸,但某些情況下,ex的表現(xiàn)相當出色。如:我們需要如下效果
需要在文字后面加一個倒三角符號,這時候我們要讓文字和圖標對齊可能會借助vertical-align:middle,讓文字和圖片都基于中線對齊,事實上由于文字本身是基于baseline排版的,這時候我們只要讓icon也基于baseline布局不就行了嗎?那怎么讓圖標也基于基線布局呢?加個height:1ex不就完事了嗎?如下所示:
<style> .icon-arrow {display: inline-block;width: 20px;height: 1ex;background: url(/images/5/arrow.png) no-repeat center; } </style> 復制代碼2.內(nèi)聯(lián)元素中真實存在的“行框盒子”
由于之前沒有好好解析內(nèi)聯(lián)盒子的基礎知識,這里要補充一個關于內(nèi)聯(lián)盒子的基礎內(nèi)容,這對于學習后面的知識有一定的幫助。首先我們需要明確兩個非官方概念:什么是行框盒子以及行框盒子有什么用?
什么是行框盒子?事實上我并不敢說這是官方給出的一個盒模型,作者也沒有提到,但他似乎真實存在于文字的每一行,而且是以行作為計算單位的,也就是每一行文字(不管他們是不是一個內(nèi)聯(lián)標簽或匿名標簽生成的),都在外面自動生成一個“行框盒子”。注意,這里僅代表我從書本上獲取的觀點,在后面的幽靈節(jié)點中會繼續(xù)探討官方是否給出了這個盒子。這么說可能不夠直觀,來看一個例子吧。
這是我用span標簽生成的一段話,他被瀏覽器自動分割成了兩行,你可以理解每行文字的外包裹就是一個行框盒子。那么什么時候會生成行框盒子呢?這里我僅憑個人測試提出兩種生成行框盒子的情況,第一種,就是非空內(nèi)聯(lián)元素,注意這個非空,很關鍵,作者似乎總是忽略空元素的測試,我本人則對空元素比較在意。第二種,就是inline-block元素內(nèi)部自動生成,注意這里可以為空了,具體為什么我也不知道,測試結果如此。
第二個問題是,行框盒子有什么用?作者為什么要提出行框盒子?因為這有助于我們理解很多問題。首先來看下面這個測試代碼以及他們生成的結果。
<div style="background: yellow;"><span style="line-height: 40px">我行高40px</span><span style="line-height: 60px">我行高60px</span><span style="line-height: 30px">我行高30px</span><span style="line-height: 90px">我行高90px</span> </div> 復制代碼此時div的角色就像是“行框盒子”,因為div包裹了一行“行框盒子”(這里只有一行,兩行情況又不同了),這樣做是為了讓你更直觀的看到最終這些內(nèi)聯(lián)元素最終生成的“行框盒子”,生成的高度是90px,也就是說,同一行!內(nèi)聯(lián)元素生成的行框盒子的高度,取決于line-height最高的那個元素。為了加深你對這個結果的印象,我再放一張圖,還是剛才那幾個元素,這次我把父容器div的寬度壓縮了。
最終結果跟上面測試的結論相同,第一行行高最高的是60px,第二行行高最高的是90px,兩個“行框盒子”一相加,得到最終的150px,對于行框盒子的印象應該夠深了吧!
3.內(nèi)聯(lián)元素的基石line-height
明白了行框盒子的概念之后,再來看line-height,就會容易的多了。作為內(nèi)聯(lián)元素的基石,line-height完全掌控了內(nèi)聯(lián)盒子的高度,注意,我說的是完全掌控,跟font-size沒有半毛錢關系。
來思考一下下面這個問題,一個空的div的高度是0,在里面寫上幾個字,他的高度就被撐開了,那么這個高度是由何而來呢?首先可以確定的是,是由新增的文字撐開的,在內(nèi)聯(lián)元素中,還有一類叫做“匿名內(nèi)聯(lián)元素”的近親,他們外面沒有包裹任何內(nèi)聯(lián)元素標簽,但事實上他們的表現(xiàn)跟內(nèi)聯(lián)元素相同,只是不能單獨定義自己的樣式(當然可以從父級去繼承一些過來,雖然繼承的權重最低,但總比沒有強)。好了,我們知道這幾個字是匿名內(nèi)聯(lián)元素了,因此高度是由這個內(nèi)聯(lián)元素的高度撐開的,那么這個內(nèi)聯(lián)元素的高度又取決于什么呢?下面我們來做兩個測試。
如結果所示,最終撐開高度的是line-height,而不是font-size。注意這里說的是非替換元素的純內(nèi)聯(lián)元素,替換元素的概念可以看一下之前的文章。之前說過padding和border可以影響元素的高度,那么在內(nèi)聯(lián)元素中,是否也可以呢?答案是:不行!但有些情況下,視覺上還是有一些偏差。如下測試
<div style="background: yellow"><span style="line-height: 40px;padding: 20px;border: 1px solid">我有padding和border</span> </div> 復制代碼由于markdown編輯器支持標簽語言,因此我們可以直接預覽最終效果如下(小提示:你可以通過瀏覽器直接檢查下面的元素看到CSS樣式)
我有padding和border因此對于純內(nèi)聯(lián)元素,他的高度計算只跟line-height相關。 line-height === 純內(nèi)聯(lián)元素height !!!
關于line-height的計算方式,作者“啰哩吧嗦”算了半天,我只總結成一個公式,line-height = font-size + 上半行距 + 下半行距 。對于CSS來講,font-size是已知的,因此他只需要計算半行距即可,至于它是怎么算的,就沒必要深究了。我只講這個計算方式會導致一種情況,第一行文字和最后一行文字的上方和下方都只有半行距的距離,中間部分則是一個行距,如對樣式有較高要求的可以考慮一下這個因素,用其他方式去彌補這里的高度差。
4.line-height在塊級元素和內(nèi)聯(lián)替換元素中的疲軟性
說完了line-height在內(nèi)聯(lián)元素中的表現(xiàn),再來說說line-height在塊級元素和內(nèi)聯(lián)替換元素中承擔什么樣的角色吧。
首先我們先來看簡單的,line-height在塊級元素中承擔一個什么樣的角色呢?答案是:屁用沒有。當然,本章第三點的第一個例子就是在塊級元素上直接寫line-height屬性,所以,還是有那么丁點作用的,這個作用是line-height無處不在的繼承屬性決定的,正好塊級元素內(nèi)的匿名內(nèi)聯(lián)元素自己寫不了樣式,那就只能繼承父級的line-height了,所以line-height最終還是作用于內(nèi)聯(lián)元素,而不是塊級元素。然后由內(nèi)聯(lián)元素生成的行框盒子相加,撐開了塊級元素的高度。
既然line-height在塊級元素中沒用,那他在內(nèi)聯(lián)替換元素中又有哪些表現(xiàn)呢?這個等講完vertical-align再總結。
5.深入line-height的各類屬性值
本節(jié)的標題讓人覺得摸不著頭腦,line-height還有別的屬性?還真沒有,line-height就一個值,只是可以有不同的類型。
line-height的默認值是normal,注意不是none,還支持數(shù)值,百分比值和具體長度值。
首先要了解一下這個看上去就不一般的normal,normal本身是一個跟font-family有關的變量,而且在不同的瀏覽器中還有不同的計算值,因此對于還原設計稿的這種要求,我們不可能用默認的normal屬性,同時由于line-height無處不在的繼承屬性,有時候不知不覺的你就把這個屬性給改了,因此normal屬性可以不討論(我們一切以實用性出發(fā))。
實際上,我們平時會設置line-height為具體的數(shù)值,如line-height:xx像素。這種做法完全適用于現(xiàn)在高要求的精致網(wǎng)站,對于需要高保真還原設計稿的需求,完全可以用用具體數(shù)值。當然也有一種情況你可以用數(shù)字或百分比,就是現(xiàn)在有很多網(wǎng)站有自己的設計標準,如微信小程序,ant-design之類的,他們會要求文章內(nèi)部的行高是字號的1.3-1.4倍,文章標題的的行高是字號的多少多少倍,這種情況下你大可以根據(jù)設計要求,用比例計算方式來寫行高。
這里我只推薦用長度值(1,2,3),而不是百分比值(100%,200%),你可能覺得1不是等于100%嘛,其實我也這么認為,一般都是按照喜好隨便挑一個。事實上,這里面問題可大了去了。
長度值和百分比值的計算方式是完全相同的。都是font-size*長度/百分比,向下取整,14*1.4 = 19.6 = 19px,注意不是四舍五入,是向下取整的。
那么長度和百分比哪里不同呢?答案是:繼承方式,就是line-height中無處不在的繼承方式不同。這里我們來看一個實例:
<div class="box box-1"><h3>標題</h3><p>內(nèi)容</p> </div> <div class="box box-2"><h3>標題</h3><p>內(nèi)容</p> </div> <style> .box { font-size: 14px; } .box-1 { line-height: 1.5; } .box-2 { line-height: 150%; } </style> 復制代碼結果如下圖所示:
最終表現(xiàn)得結果不一樣,問題就在于這個繼承方式。
使用數(shù)值,line-height = 本身的font-size*數(shù)值
使用百分比,line-height = 繼承來的line-height*數(shù)值
你會發(fā)現(xiàn),一個是基于自身的font-size,一個是基于繼承的line-height,完全不同,而且數(shù)值在大多數(shù)情況下的表現(xiàn)更優(yōu),也更符合實際情況。所以我個人推薦不要用line-height的百分比值,就當沒聽過。
6.內(nèi)聯(lián)元素line-height的“大值特性”
其實這個問題并不能單純的理解為,內(nèi)聯(lián)元素line-height取最大那么簡單,其中還包含之前所說的“行框盒子”的內(nèi)容,以及行框盒子產(chǎn)生的幽靈節(jié)點。在探索大值特性之前,我們得先了解一下,幽靈節(jié)點是什么。來看具體的實例:
<html> <head> <title></title> </head> <body> <div style="background: yellow"><span style="display: inline-block;"></span></div> </body> </html> 復制代碼注意這段代碼必須要有聲明。這段代碼的結果是:
這里的span標簽的高度確實是0,那么究竟是什么撐開了div的高度呢?就是上面提到的“幽靈空白節(jié)點”,你可以想象這個幽靈空白節(jié)點是一個沒有寬度的空白節(jié)點,當然你不要去dom結構里找他,肯定是找不到的。在了解幽靈空白節(jié)點之前,先得知道,什么時候會出現(xiàn)這個幽靈空白節(jié)點,根據(jù)我的測試,結果跟作者的描述相同。
產(chǎn)生行框盒子的前面自動生成幽靈空白節(jié)點。由于之前提到了,inline-block元素內(nèi)部可以生成幽靈空白節(jié)點,因此這里確實存一個一個看不見的內(nèi)聯(lián)元素,且他有自己的line-height。
幽靈空白節(jié)點的line-height = font-size(默認12px) * normal,因此這個幽靈空白節(jié)點就有自己的高度了,有自己的高度就撐開了inline-block的高度,inline-block又撐開了父容器的高度,那么現(xiàn)在就一切都說得通了。
做好了一切的準備工作,最后做個總結和檢測,理解了下面這個案例,你就真正理解了內(nèi)聯(lián)元素的line-height。
<div class="box box1"><span>span: line-height:20px</span> </div> <div class="box box2"><span>span: line-height:96px</span> </div> <style> .box {width: 280px;margin: 1em auto;outline: 1px solid #beceeb;background: #f0f3f9; } .box1 {line-height: 96px; } .box1 span {line-height: 20px; } .box2 {line-height: 20px; } .box2 span {line-height: 96px; } </style> 復制代碼由于markdown編輯器支持標簽語言,因此我們可以直接預覽最終效果如下(小提示:你可以通過瀏覽器直接檢查下面的元素看到CSS樣式)
span: line-height:20px span: line-height:96px上面這兩個box最終得到的高度是一樣的,為什么會這樣呢?
剛才說到,每個非空內(nèi)聯(lián)元素外面都會生出一層“行框盒子”,而每個行框盒子左邊就有一個幽靈空白節(jié)點,box1>span的line-height是20px,但他隔壁住了個幽靈空白節(jié)點,繼承了父元素的line-height:96px,我們已經(jīng)知道行框盒子的高度是由最高的內(nèi)聯(lián)元素的行高決定的,因此box1的最終高度和box2的相同,都是96px。
本章內(nèi)容過于多,vertical-align就放到下章講,學了vertical-align之后我們再來看如何結合兩者實現(xiàn)多行元素的垂直居中展示,有興趣的可以關注后續(xù)文章,點個關注。
不忘初心,方得始終
喜歡博主的童鞋可以掃描二維碼加博主好友~ 也可以掃中間二維碼入駐博主的粉絲群(708637831)~當然你也可以掃描二維碼打賞并直接包養(yǎng)帥氣的博主一枚。
轉載于:https://juejin.im/post/5d0348b4e51d45775e33f551
總結
以上是生活随笔為你收集整理的CSS进阶(7)—— 内联元素的掌管者line-height和vertical-align(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: servlet之servletRespo
- 下一篇: PWA(Progressive Web