1. 程式人生 > >CSS深入理解vertical-align和line-height的基友關係

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化,然後弄個白色背景,顯示其佔據的高度。
這裡寫圖片描述

會發現,圖片下面的間隙,依舊是那個間隙。但是,我們的理解就好理解了。回答下面幾個問題,我們就知道表現的原因了:

  1. vertical-align預設的對齊方式是?
  2. 後面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>

還有一點,是他們這倆個斷背山的複雜現象,我們明天再講,今天就到這,困了…..