你可能不知道的vertical-align

blank

你可能不知道的vertical-align

有一定基礎的同學提到vertical-align這個屬性基本都知道是用於行內元素和表格元素垂直對齊用的,但是看下如下的幾個小例子,你會不會產生一些疑惑,是不是跟我一樣覺得對這個屬性的理解還有不夠清晰的地方。如果這些問題你都知道其中的原理,那麼這篇文章就可以跳過了~

例一

html

<divclass="parent"><imgsrc ="./cat.jpg"></div>

css

.parent{background-color:#679def;}img{width:200px;}

問題:在一個沒有設置寬高的盒子中加入一個圖片什麼下面有一個邊距?

例二

html

<div><imgsrc ="./cat.jpg"></div>

css

div{width:300px;background-color:#cccccc;line-height:200px;height:200px;}img{height:190px;vertical-align:middle;}

問題:為什麼設置了vertical-align: middle;但並沒有真正得垂直居中,上邊距明顯大於下邊距?

例三

html

<div></div><div>x</div>

css

div{width:100px;height:100px;background-color:#cccccc;display:inline-block;}

效果:

問題:為什麼相同得div加上一個x兩個盒子就錯位了?

擴展學習:如果我在第二個盒子中添加overflow:auto;居然對齊了。為什麼?

<divstyle="overflow: auto">x</div>

例四

如果在上面得基礎上加上一個外層的盒子背景為藍色,並設置font-size:0px;會有怎樣的變化呢?

<divclass ="parent"><divclass ="child"></div><divclass ="child">x</div></div>

css

.parent{background-color:#679def;display:inline-block;font-size:0px;}.child{width:100px;height:100px;background-color:#cccccc;display:inline-block;}

問題:為什麼第二個盒子的底部完全跟第一個盒子的頂部邊緣對齊了?

例五

如果把父盒子的font-size:0px去掉,顯示出x的參考值,然後再父盒子添加line-height:300px的css屬性。

html不變

<divclass="parent"><divclass="child"></div><divclass="child">x</div></div>

css 添加一個行高line-height: 300px;

.parent{background-color:#679def;display:inline-block;line-height:300px;}.child{width:100px;height:100px;background-color:#cccccc;display:inline-block;}

效果

問題:很神奇的變化,為什麼第二個元素頂頭了呢而它的子元素沒有再盒子內而是與第一個盒子的底部對齊?

下面我來說明一下上面例子的原因,上面很多的例子都沒有使用vertical-align這個屬性,但是都實實在在跟這個屬性有關係。

如果對這個屬性沒有接觸過的同學可以先下vertical-align說明,可以點擊這裡

例一解答:

其實vertical-align有個默認屬性baseline就是使元素的基線與父元素的基線對齊。

並且vertical-align屬性是有前提的,就是必須在行內元素才會起作用,例如img ,span,或者在css中設置display:inline或display:inline-block

blank
  • 紅線:線高的頂部和底部邊緣
  • 綠線:字體的高度
  • 藍線:基線

這張圖讓我想起了小時候學習用的拼音格子^_^,這裡最主要的是對基線的了解,如果了解了img默認的基線為自己的底部和vertical-align屬性默認是元素的基線對齊父元素的基線這個兩個知識點,那麼例一的問題的就迎刃而解了,下邊距其實是父元素基線到底部的距離。

那麼我們有什麼辦法去掉下面的距離呢?

1.把父元素的font-size:0px。

這樣設置的話行內普通流的高度就0,高度消失了基線到底部的距離也就消失了(自己的理解,如果有錯誤歡迎在評論區說明)

2.在img中添加vertical-align:bottom

第一種方式其實有很大問題的,這樣設置的話,會影響所有子元素的文本大小,所以建議採用第二種方式,讓當前元素的基線跟父元素的底部對齊而不是基線。

例二解答:

這裡有幾個讓人感到困惑的點,我來逐一說明一下~

1.因為img的行內元素,它對齊是父元素的行高+文本高度而不是父元素的height,很多人在添加這個元素的時候發現不起作用,很大一部分原因是設置了高度但沒有設置行高。

2.即使設置了行高,元素的對齊也不是相對於行高上下居中,而是有一套自己的公式算法~

blank

元素的中部很好理解就是圖片的中心高度,父元素的基線之前也說過了,那麼這x-height是什麼意思呢?

blank

x-height就是上圖中x的高度,而x-height高度的一半就是這個x的中心點~

正常情況下x的垂直中心點不是父元素的垂直中心點,而且x是隨著父元素的font-size的大小變化而變化的,所以例二出現了上下邊距不一的問題。

解決方案一:設置父元素的font-size:0px

middle是指元素的中部與父元素的基線加上父元素x-height(譯註: x高度)的一半對齊

那麼如果font-size:0px的話不就指元素的中部直接指向父元素基線了嘛,而中間的普通流高度為0那麼基線也就指向了元素行高的垂直中心位置。

但是如果是在子元素下面有文本的情況下,這個方法不推薦使用,至於為什麼就不贅述了~

解決方案二:去掉父元素的line-height值,添加一個高度等於父元素的子元素,並且設置vertical-align:middle

html:

<div><imgsrc ="./cat.jpg"><divclass="middle-help"></div></div>

css

div{width:300px;background-color:#cccccc;height:200px;}img{height:190px;vertical-align:middle;}.middle-help{height:100%;vertical-align:middle;width:0px;display:inline-block;}

添加了一個寬度為0高度為100%的行內塊元素,然後添加了一個vertical-align: middle;屬性然後圖片居然居中了,這是怎麼回事?

1.首先我們要弄清一個前提,就是元素的vertical-align對齊與兄弟元素沒有任何直接關係,只於父元素有關係,那麼為什麼添加一個兄弟元素會影響到圖片?是因為這個兄弟元素影響了父元素的基線位置,而這個圖片的定位是需要父元素的基線的,所以可以說他們有間接影響~

2.第二個我們要弄清的是父元素的基線有哪些因素可以影響?因為父元素的基線才是弄懂vertical-align的關鍵。目前我知道的影響因素有這麼幾種

  • 父元素的font-size
  • 父元素的line-height
  • 某個子元素的對齊方式

其中前兩點都很好理解,最後一點我不知道用怎樣合適的語言去表達^_^(還是圖解吧~)

先放一個帶灰色背景的div盒子,並設置寬高,在div中添加一個x,如下圖,紅色為基線

然後我們在這個盒子中添加一張圖片,這時圖片vertical-align默認為元素基線對齊父元素基線,元素基線為圖片底部。父元素的基線就被被子元素拉下來了。

如果把圖片vertical-align設置成middle,然後去掉line-height添加一個高度為100%的子元素代碼如下

html

< div > x < img src = "./cat.jpg" > < div class = "middle-help" ></ div > </ div >

css

div{width:300px;background-color:#cccccc;height:200px;}img{height:100px;vertical-align:middle;}.middle-help{height:100%;vertical-align:middle;width:1px;background-color:black;display:inline-block;}

效果:

  • 紅線代表父元素基線
  • 黃線代表父元素基線加上x-height的一半,即子元素中心對齊的線

這樣那個高度為100%的元素中部正好對應是父元素的基線+ x-height/2,這樣實現了元素的對齊

擴展:為什麼要去掉line-height:200px?因為設置行高會影響子元素的基線,相對於上面會使基線下移,而父元素總是參考最下方的基線位置。下圖為父元素添加了line-height:200px,可以看到父元素基線被下拉的一點點。

例三解答:

因為行內塊元素如果內部沒有文字的時候它的基線為元素底部,如果有文字則為內部文字基線位置,細心的同學會發現,第二個盒子字母x的底部是和第一個盒子的元素底部對齊的。

那為什麼添加overflow:auto;就對齊了呢?那就要看下overflow本身了,屬性詳情點擊這裡

blank

例四解答:

如果以上的內容都理解,那麼這個問題也就很好解答了,因為第二個盒子的文本高度被壓成了一條線,那麼第二個盒子的頂部就相當於基線的位置了。

例五解答:

這個現像看上去很奇怪,是因為第二個盒子中的x為什麼不在盒子之內,是因為第二個盒子繼承了父元素的行高,而行高大於元素本身的高度,所以就擠出了盒子,而第一個盒子的對齊其實也很好理解,對齊的是父元素的基線,而父元素的基線被第二個盒子拉了下來。

參考鏈接:

vertical-align

CSS基線之道

利用vertical-align:middle垂直居中

如果你覺得這篇文章對你有幫助,請點贊和關注,非常感謝。如果有疑問,或者說錯的地方,歡迎在評論區留言批評指正~

What do you think?

Written by marketer

blank

React Router+React-Transition-Group實現頁面左右滑動+滾動位置記憶

blank

Vue – Table表格渲染上千數據優化