CSS秘密花園:-垂直居中

44年前我們把人送上月球,但在CSS中我們?nèi)匀徊荒芎芎脤崿F(xiàn)垂直居中

讓一個元素水平居中對于CSS來說非常簡單:如果是一個內(nèi)聯(lián)元素,我們可以在他的父元素上設(shè)置text-align:center;如果是一個塊元素,我們可以使用margin:auto;然而,只要一想到讓一個元素垂直居中,讓人死的心都有了。
多年來,垂直居中已成為CSS的不朽神話,也是前端專業(yè)人士群體中的一個內(nèi)部笑話。原因是:
1)經(jīng)常需要使用
2)理論上看上去非常簡單
3)過去實戰(zhàn)中要實現(xiàn)是極其困難,特別是元素大小固定時

前端開發(fā)人員多年來盡所能的來解決這個問題,共中最令人不安的是使用了很多Hack手段。在這一節(jié)中,我們一起探索一些實現(xiàn)垂直居中現(xiàn)代技術(shù)。注意,有一些受歡迎的技術(shù),不在這里討論,主要是因為:
表格布局不討論(表格顯示模式),因為它需要一些冗余的HTML標簽
inline-block方法不包括,因為要使用很多Hack手段

然而,如果你對這方面感興趣,你可以閱讀Chris Coyier寫的博文《Centering in the Unknown》,里面介紹了這兩種技術(shù)。
如果沒有特殊聲明,后面示例用的HTML結(jié)構(gòu)都是在<body>
元素中插入下面的標簽

<main> 
    <h1>Am I centered yet?</h1> 
    <p>Center me, please!</p>
</main>

為了得到下圖所示效果,我們也應(yīng)用一些基本的CSS樣式,比如background
、padding等等:

Paste_Image.png

絕對定位解決方案

最早實現(xiàn)垂直居中的技術(shù)是元素需要一個固定的寬度和高度:

main {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -3em;   /* 6/2 = 3 */
    margin-left: -9em;  /* 18/2 = 9 */
    width: 18em;
    height: 6em;
}

從本質(zhì)上講,它將元素的左上角點移到視窗中心點,然后使用負的margin(使用margin-topmargin-left),而且margin的值是元素寬度和高度的一半,使元素的中心點與視窗的中心點重合。如果使用calc()
可以減少兩個樣式:

main {
    position: absolute;
    top: calc(50% - 3em);
    left: calc(50% - 9em);
    width: 18em;
    height: 6em;
}

顯然,這種方法最大的問題是,元素需要一個固定的尺寸,而需要垂直居中元素的尺寸常常是需要由它的內(nèi)容來決定。如果我們有辦法使用百分比來控制元素尺寸,我們的問題就解決了。不幸的是,對于大多數(shù)CSS屬性(包括margin)百分比的值是相對于其父元素的寬度來決定。

CSS中常??梢钥吹胶芏嘟鉀Q方案是不可思議。在這個例中,就可以使用CSS3transform??梢栽?code>transform中的translate()使用百分比,讓元素移動是相對于自身的寬度和高度,這種方案正是我們需要的。

main {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

當然,沒有哪門技術(shù)是完美的,在實際使用中要注意一下以下幾個事項:

  • 絕對定位通常不是一個很好的選擇,因為它對整體的布局影響相當?shù)拇蟆?/li>
  • 如果垂直居中元素的內(nèi)容比視窗高度更高的話,它的頂部會被裁剪掉,如下圖所示。但是這個問題可以解決,只不過需要使用一些Hack手段。
  • 在一些瀏覽器中,可能會導(dǎo)致元素出現(xiàn)略微的模糊,那是因為元素有可能被放置在半個像素位置上。我們可以通過transform-style:preserve-3d來解決,盡管這是一個Hack手段,不能保證它不會過時。
Paste_Image.png

視窗單位的解決方案

如果想避免使用絕對定位,我們?nèi)匀豢梢允褂?code>translate()方法,其值剛好是元寬度和高度的一半。然而,我們?nèi)绾尾皇褂?code>top和left將元素從topleft移動50%的偏移量呢?

首先想到的是給margin屬性一個百分數(shù),像這樣:

main {
    width: 18em;
    padding: 1em 1.5em;
    margin: 50% auto 0;
    transform: translateY(-50%);
}

然而,正如你所看到的效果,如下圖所示:

Paste_Image.png

這產(chǎn)生了非常奇怪的效果。主要原因是margin的百分比計算是相對于父容器的width來計算。是這樣的,甚至包括margin-topmargin-bottom

值得慶幸的是,如果我們想讓元素在視窗中居中,還是有希望的。CSS Values and Units Level 3定義了一種新的單位,稱為相對視窗(viewport-relative)長度單位。vw是相對于視窗的寬度。與你預(yù)期剛好相反,1vw相當于視窗寬度的1%,而不是100%
vw相似的是,1vh相當于視窗高度的1%
如果視窗的寬度小于高度,1vmin等于1vw,反之,如果視窗寬度大于高度,1vmin等于1vh
如果視窗的寬度大于高度,1vmax等于1vw,反之,如果視窗寬度小于高度,1vmax等于1vh
在這個示例中,我們需要給margin的值設(shè)置vh單位:

main {
    width: 18em;
    padding: 1em 1.5em;
    margin: 50vh auto 0;
    transform: translateY(-50%);
}

正如你看到效果很完美。

Paste_Image.png

當然,這種方法有用性是有極限的,因為它只適用于元素在視窗中垂直居中。

請注意,還可以使用相對視窗單位來創(chuàng)建全屏效果,而且不需要使用任何腳本。更多細節(jié)可以閱讀Andrew Ckor寫的《Make full screen sections with 1 line of CSS》博文。

Flexbox的解決方案

這無疑是最好的解決方案,因Flexbox的出現(xiàn)就是為了解決這樣的問題。其他解決方案仍然可用,唯一原因是他們能更好的在瀏覽器上呈現(xiàn),不過Flexbox在現(xiàn)代瀏覽器也得到更好的好支持。
只需要兩個樣式,在需要垂直居中的父元素上設(shè)置display:flex
(這個示例中就是<body>)和在垂直居中的元素上設(shè)置margin:auto(這個示例中就是<main>):

body {
    display: flex;
    min-height: 100vh;
    margin: 0;
}

main {
    margin: auto;
}

注意,當使用Flexboxmargin:auto時,元素不僅水平居中,而且也會垂直居中。也注意,我們甚至沒有設(shè)置寬度(如果我們想要也可以設(shè)置),其實指定的寬度相當于max-content

如果瀏覽器不支持Flexbox,那么結(jié)果看起來就會像下圖(如果我們給元素設(shè)置了寬度):

Paste_Image.png

即使不是垂直居中,還是可以接受的。

Flexbox的另一個優(yōu)點是,可以讓匿名容器垂直居中。例如,我們將結(jié)構(gòu)換成:

<main>Center me, please!</main>

我們可以通過align-itemsjustify-content屬性使設(shè)置固定尺寸的<main>容器里面的文本居中。如下圖所示:

Paste_Image.png

我們可以在<body>和需要居中的元素<main>使用相同的屬性,同時使用margin:auto做為備用,以于優(yōu)雅降級。

main {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18em;
    height: 10em;
}

新特性:對齊所有東西

CSS Box Alignment Level 3已經(jīng)在計劃,在未來我們甚至不需要使用不同的布局模式就能非常容易的實現(xiàn)垂直居中,我們只需要像下面這樣做:

align-self: center;

不管元素上使用其他樣式,這個將來都能運行。這聽起來令人難以置信,但將來在瀏覽器中是可以渲染的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽?zāi)J的外補...
    _Yfling閱讀 14,167評論 1 92
  • 收聽音頻,戳鏈接,舊號itclan已暫停使用,歡迎關(guān)注微信itclanCoder公眾號可收聽更多音頻 前言 關(guān)于網(wǎng)...
    itclanCoder閱讀 8,353評論 3 30
  • 1.絕對定位居中技術(shù) 我們一直用margin:auto實現(xiàn)水平居中,而一直認為margin:auto不能實現(xiàn)垂直居...
    DecadeHeart閱讀 1,665評論 0 3
  • 使用 CSS 實現(xiàn)居中效果困難嗎?顯然不是。實際上有許多方法可以實現(xiàn)居中效果,但在具體情況中,我們往往無法判斷哪種...
    啊啊啊滿閱讀 349評論 0 0
  • 上一章 目錄 娘親和爹爹自遠處急急匆匆而來,望見我將刀劍舉過頭頂,雙眼赤紅,戾氣騰騰。而我眼前的云裳瞪圓了眼睛,無...
    末曉閱讀 534評論 0 10

友情鏈接更多精彩內(nèi)容