1. 程式人生 > >line-height和vertical-align實現多行文字水平垂直居中效果

line-height和vertical-align實現多行文字水平垂直居中效果

這篇文章源於同事問了我兩個問題:

(1)為什麼height和line-height設定相同的值能夠使得單行文字垂直居中?
(2)如何實現多行文字水平垂直居中效果?

經過學習,大致形成了自己的思路,也順利解決了同事的疑惑,覺得有必要寫篇文章記錄,一來是給自己做備忘,二來是給恰好有此疑惑的同行一個解決問題的思路,鑑於本人水平有限,文中不當之處歡迎批評指教.

(一)從文字和圖片的間隙說起:

文字與圖片的間隙

程式碼如下:
<style>
  .box {
           background-color: green;
       }
       .box
> img { width: 100px; height: 100px; }
</style> <div class="box"> this is a picture<img src="3.png" </div>

當你無法理解某項概念的時候,很有可能你遺漏了某些底層的知識,我們來看看要理解這個概念,我們需要哪些知識.

1、line-height與行距
1.1 行距

兩行文字之間的距離,與傳統印刷行業等不同,css中行距分別在一行的上下,各佔一半,稱半行距

1.2 line-height與半行距的關係

line-height - 半行距 = 1 embox的作用範圍,1em box可以近似理解為font-size的作用範圍或者文字選中的範圍

1.3 line-height的預設值normal以及和font-size的關係;

line-height具有繼承性,預設值為normal,且與font-size和font-family緊密相關,css規範中規定為font-size的1.0~1.2倍。

1.4 line-height的作用物件

對於inline和inline-block元素作用於元素自身,對於block元素,子元素通過繼承被作用

1.5 line-height與替換元素

line-height只能決定行框盒子的最小高度(行框盒子後面會講),img高度大於line-height的時候,line-height是不起作用的

有了知識1,我們已經可以解決同事的第一個問題:為什麼height和line-height設定相同的值能夠使得單行文字垂直居中?
<style>
    div {
        height: 50px;
        line-height: 50px;
        background-color: green;
    }
    span {
        background-color: yellow;
    }
</style>
<div>
    <span>這裡是文字這裡是文字這裡是文字這裡是文字這裡是文字這裡是文字</span>
</div>
事實是:單行文字的居中與height無關,只需要一個line-height就可以實現.
<style>
    div {
        line-height: 50px;
    }
</style>
對於多行文字而言,效果是這樣的,可以看到,block元素的高度可以通過inline元素的高度疊加撐起來,同時加上盒子模型的padding, margin, border,就構成了css中內容的高度

多行文字

下面回到我們之前文字和圖片空隙的問題,瞭解這一點,還需要vertical-align的知識

2、vertical-align的作用範圍&&vertical-align: baseline(基線)
2.1 各種線

各種線

2.2 line-height作用範圍以及預設作用vertical-align: baseline
(1)inline:如文字

預設font-size下x的基線為基準,以各自的基線進行對齊,但注意不同font-size和font-family的文字的基線是不一樣的

(2)inline-block:

預設font-size下x的基線為基準,如果裡面沒有inline元素(類似img,或者空span設定了display:inline-block),或者overflow不是visible,該元素的基線就是其margin的底;如果有inline元素,其基線就是最後一行inline元素的基線

(3)block:不起作用

現在可以解決我們的疑問了.文字和圖片是按照基線來對齊的,因此下面出現的空隙就是半行間距

終於鬆了一口氣,可是當我們把img標籤前面的文字去掉, 卻驚人地發現,效果還是和原來一樣,空隙依然存在!!!

<div class="box">
       <img src="3.png" alt="">
    </div>

無文字圖片間隙

要理解這一點,就要引入另外兩個概念:行內框盒子模型與幽靈空白節點

3.行內框盒子模型

這裡寫圖片描述

3.1 幽靈空白節點

瀏覽器在渲染的時候,會每一個行框盒子(linebox)前面渲染一個寬度為零高度為行高的空白節點,就跟文字的表現一樣

我們現在來解釋一個圖片的間隙:

首先:瀏覽器有預設的font-size,如在chrome中為16px,
其次:line-height不作用於外部的div,作用於內部的元素,line-heiht預設的屬性值為normal, 為font-size的1.0~1.2倍,具體由瀏覽器決定,導致了行間距和半行間距大於0
再次:文字和圖片按基線對齊,因此底部會出現寬度為半行距的空隙
最後:由於瀏覽器的渲染機制,導致空白節點的表現和文字的變現一樣.

搞清楚原理之後,我們可以著手來消除這個間隙

方法一:設定vertical-align:top/middle/bottom
.box > img {
      vertical-align: middle;
 }
方法二:將img設定為block元素
.box > img {
     display: block;
 }
方法三:去除行間距,line-height或者font-size為0
.box {
      line-height: 0;
      /*font-size: 0;*/
}

(二)實現多行文字垂直居中效果

<style>
    .container {
        height: 300px;
        line-height: 300px;
        background-color: red;
        text-align: center;
       overflow: hidden;
    }
    .content {
        display: inline-block;
        width: 200px;
        height: 200px;
        line-height: 20px;
        vertical-align: middle;
        text-align: left;
        background-color: yellow;
    }

</style>
<div class="container">
   <span class="content">這裡是文字這裡是文字這裡是文字這裡是文字這裡是字這裡是字這裡是字這裡是字這裡是字這裡是字這裡是字這裡是文字這裡是文字這裡是文字這裡是文字這裡是文字這裡是文字這裡是文字</span>
</div>
效果如下:

>.png

原理根本在於為外部的container和內部的content設定不同的line-height,利用幽靈空白節點和content的vertical-align: middle對齊來實現垂直居中效果
1.span為內聯元素,其內容形成一個內聯盒子,進而形成一個行框盒子(line box)
2.瀏覽器在渲染的時候會在每個line-box前面渲染一個空白節點,container高度由這個節點的line-height撐起
3.利用vertical-align:middle實現與幽靈空白節點的居中對齊
4. 設定為inline-block可以對content的寬高進行設定

總結:實現垂直居中的效果還有其他的方法,這裡只是提供了一種思路,本文主要參考了《css世界》中的內容,並且進行了按照自己的邏輯簡化,避免了事無鉅細的描述,如想了解更多,可以讀一下此書。