重學css(6)內(nèi)聯(lián)元素的掌管者line-height和vertical-align(上)

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的寬度壓縮了。

image.png

最終結(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)元素的高度又取決于什么呢签财?下面我們來做兩個測試。

image.png

如結(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ù)文章辛馆,點個關注俺陋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市昙篙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诱咏,老刑警劉巖苔可,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異袋狞,居然都是意外死亡焚辅,警方通過查閱死者的電腦和手機映屋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來同蜻,“玉大人棚点,你說我怎么就攤上這事⊥迓” “怎么了瘫析?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長默责。 經(jīng)常有香客問我贬循,道長,這世上最難降的妖魔是什么桃序? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任杖虾,我火速辦了婚禮,結(jié)果婚禮上媒熊,老公的妹妹穿的比我還像新娘奇适。我一直安慰自己,他們只是感情好芦鳍,可當我...
    茶點故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布嚷往。 她就那樣靜靜地躺著,像睡著了一般怜校。 火紅的嫁衣襯著肌膚如雪间影。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天茄茁,我揣著相機與錄音魂贬,去河邊找鬼。 笑死裙顽,一個胖子當著我的面吹牛付燥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愈犹,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼键科,長吁一口氣:“原來是場噩夢啊……” “哼惠拭!你這毒婦竟也來了娃循?” 一聲冷哼從身側(cè)響起筑悴,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤漓滔,失蹤者是張志新(化名)和其女友劉穎趋观,沒想到半個月后痘番,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體醉冤,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蓖宦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年叁执,在試婚紗的時候發(fā)現(xiàn)自己被綠了茄厘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矮冬。...
    茶點故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖次哈,靈堂內(nèi)的尸體忽然破棺而出胎署,到底是詐尸還是另有隱情,我是刑警寧澤窑滞,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布琼牧,位于F島的核電站,受9級特大地震影響葛假,放射性物質(zhì)發(fā)生泄漏障陶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一聊训、第九天 我趴在偏房一處隱蔽的房頂上張望抱究。 院中可真熱鬧,春花似錦带斑、人聲如沸鼓寺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妈候。三九已至,卻和暖如春挂滓,著一層夾襖步出監(jiān)牢的瞬間苦银,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工赶站, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留幔虏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓贝椿,卻偏偏與公主長得像想括,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子烙博,可洞房花燭夜當晚...
    茶點故事閱讀 43,666評論 2 350

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

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案瑟蜈? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,741評論 1 92
  • 參考文章:深入了解CSS的line-height屬性Vertical-Align: 你需要知道的所有事【譯】Ver...
    若邪Y閱讀 3,428評論 1 6
  • 本文原創(chuàng):liruifang 作為一個前端人,經(jīng)吃埽混跡于圖片和文字相互糅雜的江湖中铺根,稍有不慎便會中招,本文主要從l...
    jad_design閱讀 1,509評論 0 6
  • vertical-align 先看一個例子 baseline(默認值)基線,盒子的基線大約在其內(nèi)部文字(匿名)盒子...
    吳立寧閱讀 2,528評論 0 4
  • 《水滸傳》是一部深受人們喜愛的古代經(jīng)典名著乔宿,隨著新版電視劇的熱播夷都,梁山好漢的形象又一次鮮活地走進了千家萬戶...
    生活與興趣閱讀 1,282評論 1 0