老生常談之CSS的垂直居中

2021-09-10 05:43:37 字數 3273 閱讀 7013

「44 年前我們就把人類送上月球了,但現在我們仍然無法在 css 中 實現垂直居中。」

——james anderson( status/358603820516917249)

在 css 中對元素進行水平居中是非常簡單的:如果它是乙個行內元素, 就對它的父元素應用text-align: center;如果它是乙個塊級元素,就對它自身應用margin: auto。然而如果要對乙個元素進行垂直居中,可能光是想想就令人頭皮發麻了。

長久以來,為了解決這一絕世難題,前端開發者們殫精竭慮,琢磨出了各種解決方法,可惜大多數並不實用。在本篇攻略中,我們將探索現代 css 的強大威力,以全新的思路去攻克各種場景下的垂直居中難題。請注意,有幾種技巧十分流行,但在這裡並不會深入**,原因如下:

我們將使用如下所示的結構**,並直接插入 元素中(但實際上我們將要探索的這些技巧是與容器無關的):

我們先來看乙個早期的垂直居中方法,它要求元素具有固定的寬度和高度:

main
這段**在本質上做了這樣幾件事情:

先把這個元素的左上角放置在視口(或最近的、具有定位屬性的祖先元素)的正中心

然後再利用負外邊距把它向左、向上移動(移動距離相當於它自身寬高的一半),從而把元素的正中心放置在視口的正中心。

借助強大的calc()函式,這段**還可以省掉兩行宣告:

main
顯然,這個方法最大的侷限在於它要求元素的寬高是固定的。

在通常情況下,對那些需要居中的元素來說,其尺寸往往是由其內容來決定的。如果 能找到乙個屬性的百分比值以元素自身的寬高作為解析基準,那我們的難題就迎刃而解了!遺憾的是,對於絕大多數 css 屬性(包括 margin)來說, 百分比都是以其父元素的尺寸為基準進行解析的。

css 領域有乙個很常見的現象,真正的解決方案往往來自於我們最意想不到的地方。

在這個例子中,答案來自於 css transforms 。當我們在translate()變形函式中使用百分比值時,是以這個元素自身的寬度和高度為基準進行換算和移動的,而這正是我們所需要的。接下來,只要換用基於百分比的 css 變形來對元素進行偏移,就不需要在偏移量中把元素的尺寸寫死。這樣我們就可以徹底解除對固定尺寸的依賴:

main
可以看到,這個容器已經完美居中了,完全滿足我們的期望。 

當然,沒有任何技巧是十全十美的,上面這個方法也有一些需要注意的地方:

線上例子:
假設我們不想使用絕對定位,仍然可以採用translate()技巧來把這 個元素以其自身寬高的一半為距離進行移動;但是在缺少 left 和 top 的情況下,如何把這個元素的左上角放置在容器的正中心呢?

我們的第一反應很可能是用 margin 屬性的百分比值來實現,就像這樣:

main
不過,如圖所示,這段**會產生十分離譜的結果:

原因在於margin 的百分比值是以父元素的寬度作為解析基準的。沒錯,即使對於margin-topmargin-bottom來說也是這樣!

不過幸運的是,如果只是想把元素相對於視口進行居中,仍然是有希望的。css values and units module level 3 定義了一套新的單位,稱為 viewport 相關的長度單位。

在我們的這個例子中,適用於外邊距的是 vh 單位:

main
可以看到,其效果堪稱完美。當然,這個技巧的實用性是相當有限的,因為它只適用於在視口中居中的場景。

線上例子:
這是毋庸置疑的最佳解決方案,因為 flexbox 是專門針對這類需求所設計的。我們之所以要討論其他方案,僅僅是因為那些方案在瀏覽器的支援程度上稍微好一些而已。但其實目前現代瀏覽器對 flexbox 的支援度已經相當不錯了。

我們只需寫兩行宣告即可:

body 

main

請注意,當我們使用 flexbox 時,margin: auto 不僅在水平方向上將元素居中,垂直方向上也是如此。還有一點,我們甚至不需要指定任何寬度(當然,如果需要的話,也是可以指定的):這個居中元素分配到的寬度等於max-content

如果瀏覽器不支援 flexbox,頁面渲染結果看起來就跟我們的起點圖是一樣的了(如果設定了寬度的話)。雖然沒有垂直居中效果,但也是完全可以接受的。

flexbox 的另乙個好處在於,它還可以將匿名容器(即沒有被標籤包裹的文字節點)垂直居中。舉個例子,假設我們的結構**是:

center me, please!
我們先給這個 main 元素指定乙個固定的尺寸,然後借助 flexbox 規範 所引入的align-itemsjustify-content屬性,我們可以讓它內部的文字也實現居中:

main
線上例子:
根據 css box alignment module level 3 的計畫,在未來,對於簡單的垂直居中需求, 我們完全不需要動用特殊的布局模式了。因為只需要下面這行**就可以搞定:

align-self: center;
不管這個元素上還應用了其他什麼屬性,這樣寫就夠了。這聽起來可能難以置信,但或許你電腦上的瀏覽器很快就會讓它成為現實。

老生常談session,cookie的區別,安全性

一,為什麼session,cookie經常會有人提到 做web開發的人基本上都會用session和cookie,但是僅僅只是會用,並不知道session和cookie的真正的工作原理,都只是憑著感覺來猜測。web開發者只要利用它們來完成工作就行了,所以每個人的理解基本都會有大同小異,我想這就是ses...

老生常談session cookie的區別 安全性

一,為什麼session,cookie經常會有人提到 做web開發的人基本上都會用session和cookie,但是僅僅只是會用,並不知道session和cookie的真正的工作原理,都只是憑著感覺來猜測。web開發者只要利用它們來完成工作就行了,所以每個人的理解基本都會有大同小異,我想這就是ses...

老生常談 與equals的區別

最近在研究string,看到面試題有一題是 與equals的區別的題目。關於 與equals的區別相信大家很熟悉了,包括我也看到也是腦中一閃而過,比較的是位址,equals比較的是內容。真是這樣嗎?或者說能具體或深入的解釋下嗎?如果被面試官這樣問,會如何作答呢?由於最近看了string和object...