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)部自動生成,注意這里可以為空了颗味,具體為什么我也不知道超陆,測試結(jié)果如此。
第二個問題是浦马,行框盒子有什么用时呀?作者為什么要提出行框盒子?因為這有助于我們理解很多問題晶默。首先來看下面這個測試代碼以及他們生成的結(jié)果谨娜。
<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最高的那個元素滩愁。為了加深你對這個結(jié)果的印象,我再放一張圖辫封,還是剛才那幾個元素硝枉,這次我把父容器div的寬度壓縮了。
最終結(jié)果跟上面測試的結(jié)論相同倦微,第一行行高最高的是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)元素相同懦傍,只是不能單獨定義自己的樣式(當然可以從父級去繼承一些過來雹舀,雖然繼承的權(quán)重最低,但總比沒有強)粗俱。好了说榆,我們知道這幾個字是匿名內(nèi)聯(lián)元素了,因此高度是由這個內(nèi)聯(lián)元素的高度撐開的寸认,那么這個內(nèi)聯(lián)元素的高度又取決于什么呢签财?下面我們來做兩個測試。
如結(jié)果所示偏塞,最終撐開高度的是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的計算方式剥槐,作者“啰哩吧嗦”算了半天,我只總結(jié)成一個公式宪摧,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再總結(jié)筹淫。
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長度/百分比鞋拟,向下取整骂维,141.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>
結(jié)果如下圖所示:
最終表現(xiàn)得結(jié)果不一樣,問題就在于這個繼承方式懈叹。
使用數(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é)點是什么。來看具體的實例:
<!DOCTYPE HTML>
<html>
<head>
<title></title>
</head>
<body>
<div style="background: yellow"><span style="display: inline-block;"></span></div>
</body>
</html>
注意這段代碼必須要有聲明臼氨。這段代碼的結(jié)果是:
這里的span標簽的高度確實是0掺喻,那么究竟是什么撐開了div的高度呢?就是上面提到的“幽靈空白節(jié)點”储矩,你可以想象這個幽靈空白節(jié)點是一個沒有寬度的空白節(jié)點感耙,當然你不要去dom結(jié)構(gòu)里找他,肯定是找不到的持隧。在了解幽靈空白節(jié)點之前即硼,先得知道,什么時候會出現(xiàn)這個幽靈空白節(jié)點屡拨,根據(jù)我的測試只酥,結(jié)果跟作者的描述相同褥实。
產(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)在就一切都說得通了怎棱。
做好了一切的準備工作,最后做個總結(jié)和檢測绷跑,理解了下面這個案例拳恋,你就真正理解了內(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之后我們再來看如何結(jié)合兩者實現(xiàn)多行元素的垂直居中展示,有興趣的可以關注后續(xù)文章辛馆,點個關注俺陋。