CSS深入理解vertical-align和line-height的基友关系
生活随笔
收集整理的這篇文章主要介紹了
CSS深入理解vertical-align和line-height的基友关系
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1. vertical-align
眾所周知,vertical-align支持很多屬性值,足足可以組成一個足球隊了:
其中,有個屬性值暴露了vertical-align和line-height之間的基友關(guān)系,大家猜猜看是哪個屬性值?哇塞,好厲害!居然被大家一眼就看出來了,沒錯,就是“百分比值”
vertical-align的百分比值不是相對于字體大小或者其他什么屬性計算的,而是相對于line-height計算的。舉個簡單的例子,如下CSS代碼:
實際上,等同于:
2. 和line-height背地里無處不在的基友關(guān)系
2.1 基本現(xiàn)象
要八卦vertical-align和line-height之間的關(guān)系,我們不妨從一個極其簡單的現(xiàn)象入手。假設(shè),我們有一個標簽,然后,里面有一張圖片,我們的HTML代碼就是這樣子:
然后,表現(xiàn)就是一張圖片呈現(xiàn),類似下面這樣:
恩,看上去很正常,一切都是理所當然。然而,如果我們給這個元素增加一個背景色,例如淡藍色:
會發(fā)現(xiàn)圖片下面有一段空白空間:
實際上,這段空白間隙就是vertical-align和line-height攜手搞的鬼!首先,大家一定要意識到這么一點:對于內(nèi)聯(lián)元素(inline),vertical-align與line-height雖然看不見,但實際上「到處都是」!
2.2 幽靈空白節(jié)點
還是上面的圖片下邊緣留空隙的例子,實際上,這種行為表現(xiàn),就跟圖片前面或者后面有一個寬度為0的空格元素表現(xiàn)是一致的。但是,空格是透明的,為了便于大家理解,我就直接使用很明顯的匿名inline box, 也就是字符代替。如下,大家會發(fā)現(xiàn),圖片下面的間隙,依舊是那個間隙
下面要解釋這個間隙就好解釋了。下面,我們讓新增的文本inline-block化,然后弄個白色背景,顯示其占據(jù)的高度
1. vertical-align默認值是baseline, 也就是基線對齊。而基線是什么,基線就是字母X的下邊緣(參見“字母’x’在CSS世界中的角色和故事”一文)。所以,妹子圖片的下邊緣就和后面zxx中的字母x下邊緣對齊(見下圖)。而字符zxx本身是有高度的,對吧,于是,圖片下面就留空了
2. 而zxx文字的高度是由行高決定的
因此,簡單的圖片下面留白行為表現(xiàn),本質(zhì)上,就是vertical-align和line-height背地里搞基造成的。
既然我們找到了這個問題的所在,那么我們現(xiàn)在搞定這對基友中的隨便一個不就可以了嗎?
★ 讓vertical-align失效
圖片默認是inline水平的,而vertical-align對塊狀的元素無感。因此,我們只要讓圖片display水平為block就可以了,我們可以直接設(shè)置display或者浮動、絕對定位等(如果布局允許)。例如:
★ 使用其他vertical-align值
告別baseline, 取用其他屬性值,比方說bottom/middle/top都是可以的
★ 直接修改line-height值
下面的空隙高度,實際上是文字計算后的行高值和字母x下邊緣的距離。因此,只要行高足夠小,實際文字占據(jù)的高度的底部就會在x的上面,下面沒有了高度區(qū)域支撐,自然,圖片就會有容器底邊貼合在一起了。比方說,我們設(shè)置行高5像素
★ line-height為相對單位,font-size間接控制
如果line-height是相對單位,例如line-height:1.6或者line-height:160%之類,也可以使用font-size間接控制,比方說來個狠的,font-size設(shè)為大雞蛋0, 本質(zhì)上還是改變line-height值
3. 基本現(xiàn)象衍生:垂直居中
由于「幽靈空白節(jié)點」的存在,因此,我們可以進一步衍生,實現(xiàn)其他更實用的效果,比方說任意尺寸的圖片(或者內(nèi)聯(lián)塊狀化inline-block的多行文字)的垂直居中效果。就是借助本文的兩位男主角,vertical-align和line-height
在HTML5文檔聲明下,塊狀元素內(nèi)部的內(nèi)聯(lián)元素的行為表現(xiàn),就好像塊狀元素內(nèi)部還有一個(更有可能兩個-前后)看不見摸不著沒有寬度沒有實體的空白節(jié)點在對內(nèi)聯(lián)元素起著作用,這個假想似乎存在的空白節(jié)點,我稱之為“幽靈空白節(jié)點”
你想啊,圖片(塊狀元素內(nèi)部的內(nèi)聯(lián)元素)后面(前面)有個類似空格字符的節(jié)點,然后就能響應(yīng)line-height形成高度來達到文字的居中,此時,圖片再來個vertical-align:middle,當當當當,就可以和這個被行高撐高的「幽靈空白節(jié)點」(近似)垂直對齊了
不過上面的效果并不是完全的垂直居中,只是近似(稍微仔細看可以看出來)。為什么只是近似呢?那是因為「幽靈空白節(jié)點」高度行高撐開,其垂直中心是字符content area的中心,而對于字符x而言,都是比絕對中心位置要下沉的(不同字體下沉幅度不一樣),換句更易懂的描述就是x的中心位置都是在字符內(nèi)容區(qū)域高度中心點的下方,而這上下的偏差就是這里圖片上下間距的偏差
因此,要想完全垂直居中,最先想到的方法就是讓后面的“幽靈字符”也是vertical-align:middle,然而,呵呵,既然稱之為“幽靈”就表示不會受非繼承特性的屬性影響,所以,根本沒法設(shè)置vertical-align:middle,除非你自己創(chuàng)建一個顯示的內(nèi)聯(lián)元素
我們就沒有辦法了嗎?當然不是,“幽靈字符”可以受具有繼承特性的CSS屬性影響,于是,我們可以通過其他東西來做調(diào)整,讓字符的中線和字符內(nèi)容中心線在一起,或者說在一個位置上就可以了。有人可能要疑問了,這能行嗎?啊,是可以的
怎么搞?很簡單,font-size:0, 因此此時content area高度是0,各種亂七八糟的線都在高度為0的這條線上,絕對中心線和中線重合。自然全垂直居中:
4. 復雜現(xiàn)象
多年前曾分享過“text-align:justify下列表的兩端對齊布局”的技術(shù),其中,為了讓任意個數(shù)的列表最后一行也是對齊排列,在列表最后會輔助列表等寬的空標簽元素來占位,類似下面紅色高亮HTML代碼
同樣的,在白色背景下,似乎看上去效果還不賴,但是,如果給div容器加個背景色~~,會驚訝的發(fā)現(xiàn),下面多了很大一塊間隙
為了便于大家看其究竟,我把占位i元素outline高亮下,于是,效果如下:
下面問題來了:上面的間隙是如何產(chǎn)生的?下面的間隙是如何產(chǎn)生的?如果去除這些間隙呢?很多時候,復雜問題是由簡單問題組合而成的,實際上,這里的間隙現(xiàn)象的始作俑者和上面的簡單現(xiàn)象一樣,都是vertical-align和line-height搞基帶來的不好的影響。
按照之前問題解決方法,我們可以直接來個line-height:0解決垂直間隙問題
結(jié)果圖片和圖片之間的間隙是沒有了,但是,圖片和最后的占位元素之間依然有個幾像素的間距,啊啊啊啊,這究竟是什么鬼?
簡單現(xiàn)象的背后往往有大的學問,接下來是本文的高潮了,究其原因,要說到inline-block元素和基線baseline之間的一些糾纏的關(guān)系
5. inline-block和baseline
一個inline-block元素,如果里面沒有inline內(nèi)聯(lián)元素,或者overflow不是visible,則該元素的基線就是其margin底邊緣,否則,其基線就是元素里面最后一行內(nèi)聯(lián)元素的基線。
兩個同尺寸的inline-block水平元素,唯一區(qū)別就是一個空的,一個里面有字符,代碼如下
會發(fā)現(xiàn),明明尺寸、display水平都是一樣的,結(jié)果呢,兩個卻不在一個水平線上對齊,為什么呢?哈哈,上面的規(guī)范已經(jīng)說明了一切。第一個框框里面沒有內(nèi)聯(lián)元素,因此,基線就是容器的margin下邊緣,也就是下邊框下面的位置;而第二個框框里面有字符,純正的內(nèi)聯(lián)元素,因此,第二個框框就是這些字符的基線,也就是字母x的下邊緣了。于是,我們就看到了框框1下邊緣和框框2里面字符x底邊對齊的好戲。框框2有個小彩蛋,點擊可以toggle其innerHTML,會發(fā)現(xiàn),如果框框2里面沒文字,就和框框1舉案齊眉了。
下面我們要做一件很有必要的事情,用來幫助我們理解上面復雜例子在line-height值為0后的表現(xiàn),什么事情呢?哈,同境界模擬,我們也設(shè)置框框2的line-height值為0,于是,就會是下面這樣的表現(xiàn):
知道框框2為何又下沉了一點嗎?因為字符實際占據(jù)的高度是由行高決定的,當行高變成0的時候,字符占據(jù)的高度也是0,此時,字符高度上的起始位置就不再是原來行高的值所對應(yīng)的位置a,而是變成了字符content area的垂直中心位置b,于是,文字就一半落在框框2的外面了
由于文字字符上移了,自然基線位置(字母x的底邊緣)也往上移動了,于是,兩個框框的垂直落差就更大了
OK,明白了上面的簡單例子,也就能明白上面的復雜例子。緊接著,如果我們在最后一個占位的<i>元素后面新增同樣的x-baseline字符,則
因為line-height等于0,所以字符在垂直方向上的高度是從內(nèi)容區(qū)域的垂直中心線處開始計算,再加上圖片的默認基線是底部,所以x-baseline的垂直中線和上面一列的圖片底端對齊。雖然字符占據(jù)的高度隨著行高的改變而改變,但是其基線仍然在最下面,所以其和i標簽基線的對齊導致圖片和下邊緣的間隙
現(xiàn)在行高line-height是0, 則最后的x-baseline的垂直中線就和上面一列的圖片對齊,而基線呢,就在中線下面差不多半個x的高度地方,而這個高度落差就是最后圖片和容器的間隙高度值,因為前面的<i class="justify-fix">是個空元素,基線是自身的底部,哈哈,造業(yè)啊!
OK,一旦知道了現(xiàn)象的本質(zhì),我們就能輕松對癥下藥了!要么改造占位<i>元素的基線、要么改造“幽靈空白節(jié)點”的基線位置、要么使用其他vertical-align對齊方式~
首先,來個最有意思的方法,對吧,改造占位<i>元素的基線。這個很簡單,對吧,只要在空的<i>元素里面隨便放幾個字符就可以了,例如,里面有個x
會發(fā)現(xiàn),間隙沒有了! 為什么呢?哈哈,因為<i>元素的基線和“幽靈空白節(jié)點”的基線位置現(xiàn)在一致了,沒有了錯位,自然就不會有間隙啦!
改造“幽靈空白節(jié)點”的基線位置,哈哈,使用font-size,字體足夠小時,基線和中線會重合在一起,什么時候字體足夠小呢,就是0. 于是,CSS代碼(line-height如果是相對值,line-height:0也可以省掉):
總結(jié):
1.
總結(jié)
以上是生活随笔為你收集整理的CSS深入理解vertical-align和line-height的基友关系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 完整的JS表单验证封装类
- 下一篇: 框架高度随内容改变