從頭開始 — CSS — 垂直居中

事實上,每次面試前端必問的問題就是這個。及其常見的需求,看起來彷佛很是簡單,可是實現起來很費勁,尤爲是涉及尺寸不固定的元素。css

本篇文章將介紹比較流行的幾種方法。html

行內塊

<body>
    <div id="ghost"></div>
    <span>
        hello
    </span>
</body>
#ghost {
            display: inline-block;
            height: 20em;
            vertical-align: middle;
        }

本質上是利用了內聯元素的 vertical-align 屬性,經過將此屬性置爲middle,同一行內的內聯元素都將以設置這一屬性的內聯元素的基線對齊。前端

基於inline-block特有的屬性:擁有內聯元素的特性同時能夠定義寬高,咱們能夠設置一個ghost行內塊用於定義高度,再讓其餘內聯元素與其對齊,實現垂直居中。面試

固然咱們也能夠將其它元素置爲行內塊,再設置寬度並添加text-align使其水平居中。瀏覽器

總結一下,此方法太過hack。函數

絕對定位

子元素固定寬高

<div id="main">
        <div id="child">
            hello
        </div>
</div>
#main {
            background-color: green;
            height: 20em;
            width: 20em;
            position: relative;
}

#child {
            position: absolute;
            background: yellow;
            top: 50%;
            left: 50%;
            height: 10em;
            width: 10em;
            margin-top: -5em;
            margin-left: -5em;
}

顯然,這種方法的原理是:先利用絕對定位將這個元素的左上角放置與父元素的正中間,再利用負邊距將它向左上移動它自己的一半。佈局

若是藉助calc()函數能夠說明得更加清楚:flex

#child {
    position: absolute;
    top: calc(50%-5em);
    left: calc(50%-5em);
    height: 10em;
    width: 10em;
}

不固定寬高

實際中大多數時候咱們並不知道子元素的實際寬高。flexbox

若是你屬性translate()函數,你必定知道當它的參數爲百分比時,它會按照元素自己的百分比值進行變換,咱們能夠經過這個方法完全擺脫對尺寸的依賴!spa

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

看起來已經完美解決了,可是它還有如下的缺陷:

  1. 絕對定位會對總體的佈局形成很強烈的影響。
  2. 若是居中的元素超過了視窗會被裁剪掉。
  3. 在某些瀏覽器中,元素可能會被放置在半個像素上形成模糊。

視口居中

若是咱們不採用絕對定位,對子元素設置margin使其左上角置於父元素中點,再用translate重複上一種方法的操做,是否能夠實現呢?

答案是不能夠,由於margin的百分比是以父元素的寬度爲基準的,即使是top和bottom也是! 沒錯,很扯。

若是僅僅想要垂直於視口,咱們能夠採用css中相對於視口的單位 vwvhvminvmax

  • 1vw 表示視口寬度的1%,同理1vh等於視口高度的1%
  • 當視口寬度小於高度時,1vmin=1vw,不然1vmin=1vh,另外一種狀況同理。
#child {
            margin:50vh auto 0;
            transform: translateY(-50%);
}

它只能基於視口居中。

Flexbox

flex固然是將來的趨勢,上面的一切均可以理解成爲了照顧老舊的瀏覽器的猴戲(雖然translate和視口單位的兼容性也不怎麼好)。

<body>
    <div id="main">hello</div>
</body>
#main {
           margin: auto;
        }
 body {
            display: flex;  
        }

啊,很難受。使用flexbox時,margin:auto不只在水平方向上將元素居中,垂直方向上也是如此。

若是你熟悉flex的話,其實還有多種實現方式。

body {
            display: flex;  
            justify-content: center;
            align-items:center;
        }

或者對子元素單獨設置交叉軸對齊方式:

body {
            display: flex;  
            justify-content: center;
        }
#main {
            align-self:center;
}
相關文章
相關標籤/搜索