CSS深入理解vertical-align和line-height的基友關係
本來以為今天又要到家十來點,蹲在我的小窗戶前吭哧吭哧寫筆記,沒想到這會兒我負責的兩個頁面,介面都掛了,咩哈哈,不用回家頓小窗臺了,咩哈哈哈~
俗話說,死宅腐女還有啥來著註定單身狗,反正這三樣我確實是全佔了的,非常願意研究基腐問題,科科。
那麼看看CSS屆的vertical-align和line-height,就是典型的表面上看上去大相徑庭,實際上是大進後庭的斷背好基友!
表現明顯的斷背基情
眾所周知,vertical-align支援很多屬性值:
/* 關鍵字值 */
vertical-align: baseline;
vertical-align: sub;
vertical-align : super;
vertical-align: text-top;
vertical-align: text-bottom;
vertical-align: middle;
vertical-align: top;
vertical-align: bottom;
/* <長度> 值 */
vertical-align: 10em;
vertical-align: 4px;
/* <百分比> 值 */
vertical-align: 10%;
/* 全域性值 */
vertical-align: inherit;
vertical-align: initial;
vertical-align : unset;
其中,有個屬性值暴露了vertical-align和line-height之間的基友關係~~~
沒錯,就是“百分比值”。
vertical-align的百分比值不是相對於字型大小或者其他什麼屬性計算的,而是相對於line-height計算的。舉個簡單的例子,如下CSS程式碼:
{
line-height: 30px;
vertical-align: -10%;
}
實際上,等同於:
{
line-height: 30px;
vertical-align: -3px; /* = 30px * -10% */
}
CSS屬性何其多,偏偏跟line-height有一腿,這不是有基情那是什麼?
背地裡無處不在的基友關係
注意,vertical-align和line-height的地下基友關係從HTML5文件宣告開始的,因此,以下探討的現象,都是在頁面為HTML5宣告前提下,類似下面的doctype:
<!doctype html>
<html>
另外,下面很多效果直接就是真實演示,因此,請使用現代瀏覽器觀摩下面的內容。如果發現某些行為與描述不匹配,且瀏覽器正常,那可能是因為你訪問的並不是原出處。
① 基本現象
要八卦vertical-align和line-height之間的關係,我們不妨從一個極其簡單的現象入手。假設,我們有一個<div>
標籤,然後,裡面有一張<img>
圖片,我們的HTML程式碼就是這樣子:
<div><img src="mm1.jpg"></div>
如圖:
恩,看上去很正常,一切都是理所當然。然而,如果我們給這個<div>
元素增加一個背景色,例如粉色:
<div style="background-color:pink;"><img src="mm1.jpg"></div>
則會是下面這樣:
會發現圖片下面有一段空白空間:
想必大家都遇到過類似問題,不知大家有沒有思考過,為什麼圖片下面有留有一段間隙呢?
實際上,這段空白間隙就是vertical-align和line-height攜手搞的鬼!
首先,大家一定要意識到這麼一點:對於內聯元素,vertical-align與line-height雖然看不見,但實際上「到處都是」!
因此,對於內聯元素各種想得通或者想不通的行為表現,基本上都可以用vertical-align和line-height來解釋,以及進行行為矯正,然而,要深入理解這些行為表現,還是需要狠花一番功夫的,因此,下面的內容,請確保你有半小時充足時間細細閱讀,別的地方可是看不到的。
② 幽靈空白節點
「幽靈空白節點」這個概念是張鑫旭命名的,是我自己便於理解某些行為特徵提出的概念。規範可能有類似的概念,但名稱並非這個。 W3C規範雖然有很多行為的解釋和說明,但是,畢竟官方的東西,要求嚴謹正式,但是,也會有太乾太澀的感覺。如果快速掌握和理解這些行為表現呢?就個人而言,從兩方面入手:1.情感化認知;2. 具象化思維。
例如,稱vertical-align和line-height為好基友(包括以前稱浮動和絕對定位是兄弟),就是“情感化認知”;而這裡的「幽靈空白節點」就是“具象化思維”。
那「幽靈空白節點」是個什麼意思呢?
在HTML5文件宣告下,塊狀元素內部的內聯元素的行為表現,就好像塊狀元素內部還有一個(更有可能兩個-前後)看不見摸不著沒有寬度沒有實體的空白節點,這個假想又似乎存在的空白節點,我稱之為“幽靈空白節點”。
抽象了這個概念,絕對定位與text-align的一些行為表現,以及這裡的行為表現,就好理解了。
還是上面的圖片下邊緣留空隙的例子,實際上,這種行為表現,就跟圖片前面或者後面有一個寬度為0的空格元素表現是一致的。但是,空格是透明的,為了便於大家理解,我就直接使用很明顯的匿名inline box, 也就是字元代替。如下,大家會發現,圖片下面的間隙,依舊是那個間隙。
啊 ,截圖多了一條白色,大家就當看不見奧….
下面要解釋這個間隙就好解釋了。下面,我們讓新增的文字inline-block化,然後弄個白色背景,顯示其佔據的高度。
會發現,圖片下面的間隙,依舊是那個間隙。但是,我們的理解就好理解了。回答下面幾個問題,我們就知道表現的原因了:
- vertical-align預設的對齊方式是?
- 後面zxx文字的高度從何而來?
上面2個問題就很簡單了:
vertical-align預設值是baseline, 也就是基線對齊。而基線是什麼,基線就是字母X的下邊緣。所以,烏姆奇奧拉圖片的下邊緣就和後面ZEro中的字母x下邊緣對齊(見下圖)。而字元zxx本身是有高度的,於是,圖片下面就留空了。
而ZEro文字的高度是由行高決定的。
因此,簡單的圖片下面留白行為表現,本質上,就是vertical-align和line-height背地裡搞基造成的。
知道了問題的原因,我們就可以對症下藥,準確搞定圖片下面我們不希望看到的間隙。怎麼搞呢?一對基友,vertical-align和line-height我們隨便搞定一個就可以了。
比方說vertical-align.
1. 讓vertical-align失效
圖片預設是inline水平的,而vertical-align對塊狀水平的元素無感。因此,我們只要讓圖片display水平為block就可以了,我們可以直接設定display或者浮動、絕對定位等(如果佈局允許)。例如:
img { display: block; }
則帥奇下面的空隙就會不見。
2. 使用其他vertical-align值
告別baseline, 取用其他屬性值,比方說bottom/middle/top都是可以的。
vertical-align:bottom
vertical-align:middle
vertical-align:top
3. 直接修改line-height值
下面的空隙高度,實際上是文字計算後的行高值和字母x下邊緣的距離。因此,只要行高足夠小,實際文字佔據的高度的底部就會在x的上面,下面沒有了高度區域支撐,自然,圖片就會有容器底邊貼合在一起了。比方說,我們設定行高5畫素:
div { line-height: 5px; }
4. line-height為相對單位,font-size間接控制
如果line-height是相對單位,例如line-height:1.6或者line-height:160%之類,也可以使用font-size間接控制,比方說來個狠的,font-size設為大雞蛋0, 本質上還是改變line-height值.
div { font-size: 0; }
③ 基本現象衍生:垂直居中
由於「幽靈空白節點」的存在,因此,我們可以進一步衍生,實現其他更實用的效果,比方說任意尺寸的圖片(或者內聯塊狀化的多行文字)的垂直居中效果。就是藉助本文的兩位男主角,vertical-align和line-height。
你想啊,圖片後面(前面)有個類似空格字元的節點,然後就能響應line-height形成高度,此時,圖片再來個vertical-align:middle,噹噹噹當,就可以和這個被行高撐高的「幽靈空白節點」(近似)垂直對齊了。
例如:
div { line-height: 240px; }
img { vertical-align: middle; }
不過效果並不是完全的垂直居中,只是近似(稍微仔細看可以看出來)。為什麼只是近似呢?那是因為「幽靈空白節點」高度行高撐開,其垂直中心是字元content area的中心,而對於字元x而言,都是比絕對中心位置要下沉的(不同字型下沉幅度不一樣),換句更易懂的描述就是x的中心位置都是在字元內容區域高度中心點的下方,而這上下的偏差就是這裡圖片上下間距的偏差。
換句更簡單的話說就是:middle中線位置(字元x的中心)並不是字元內容的絕對居中位置。兩個位置的偏差就是圖片近似居中的偏差。
因此,要想完全垂直居中,最先想到的方法就是讓後面的“幽靈字元”也是vertical-align:middle,然而,呵呵,既然稱之為“幽靈”就表示不會受非繼承特性的屬性影響,所以,根本沒法設定vertical-align:middle,除非你自己建立一個顯示的內聯元素。
我們就沒有辦法了嗎?當然不是,“幽靈字元”可以受具有繼承特性的CSS屬性影響,於是,我們可以通過其他東西來做調整,讓字元的中線和字元內容中心線在一起,或者說在一個位置上就可以了。有人可能要疑問了,這能行嗎?啊,是可以的。
怎麼搞?很簡單,font-size:0, 因此此時content area高度是0,各種亂七八糟的線都在高度為0的這條線上,絕對中心線和中線重合。自然全垂直居中:
div { line-height: 240px; font-size: 0; }
img { vertical-align: middle; }
這種通過line-height定高,元素vertical-align:middle垂直居中的方法不僅適用於現代瀏覽器,連IE7瀏覽器也是支援的
不過和其他瀏覽器再使用上還是有些需要注意的地方,就是,HTML不能這樣:
<div><img src="mm1.jpg"></div>
而是需要在圖片標籤結束處留下空格後者換行:
<div><img src="mm1.jpg"><!-- 這裡要折行或空格 -->
</div>
還有一點,是他們這倆個斷背山的複雜現象,我們明天再講,今天就到這,困了…..