告別搜一次忘一次的過去,徹底總結(jié)五個垂直居中的方法.

作為一個切圖的頁面仔,工作中總是要用到垂直居中.忙的時候一般就隨便google一個復(fù)制粘貼上去,也從來沒有思考過內(nèi)在的聯(lián)系與原因,但是今天晚上聽聽音樂想看看書的時候,突然心血來潮.擇日不如撞日,就今天吧,夯實一下我的基礎(chǔ),從此讓所有垂直居中都變成紙老虎!!!

那么,先談?wù)労唵蔚拇怪本又邪?

在CSS中想要實現(xiàn)水平居中可以說是十分簡單了,行內(nèi)元素用text-align:center,塊級元素用margin:auto,元素就會乖乖的自己跑到元素水平中間去.

但是這么多年下來,垂直居中已經(jīng)成為了CSS領(lǐng)域的圣杯.

可以說,一個不能解決這個問題的人簡直是寸步難行.不管你想做一個怎樣的網(wǎng)頁,垂直居中都有很大的可能性會用到.但是,它并不簡單,甚至可以說難于登天.

為了解決這個絕世難題,前端開發(fā)者們從各個方面想出了各種不同的點子.之前也許你在百度的某個角落里找到過一些碎片,今天我嘗試將這些碎片組裝起來,還原一個真正的垂直居中,也將自己的基礎(chǔ)進行一次夯實.

1.表格布局法.

第一個想到表格布局法的人已經(jīng)無法考證,但是不得不說這真的是一個Excited的做法.

 <body>    
<div class="Center-Container is-Table">  
<div class="Table-Cell">  
<div class="Center-Block">  
<!-- CONTENT -->  
</div>  
</div>  
</div>  
</body>
<style>
.Center-Container.is-Table { display: table; }  
.is-Table .Table-Cell {  
  display: table-cell;  
  vertical-align: middle;  
}  
.is-Table .Center-Block {  
  width: 50%;  
  margin: 0 auto;  
}  
</style>

寫一個表格,將需要居中顯示的內(nèi)容放在表格正中間.自適應(yīng),內(nèi)容變方塊大小也跟著變,兼容性更是不得了.


97.72%.基本沒有不能兼容的.

嗯,所以應(yīng)該說:
表格布局法的優(yōu)點就是兼容性及其變態(tài),基本沒有不能兼容的.缺點也很明顯,需要添加冗余的HTML樣式,這在網(wǎng)頁開發(fā)中一般是不能被接受的.而且display:table有極大的可能性會擾亂整個頁面的布局,使用這種方法還是有一定風(fēng)險的.

2.行內(nèi)塊法.

這個方法的本質(zhì)是使用

display: inline-block;
vertical-align: middle;

讓一個偽元素居于容器中央.

<div class="Center-Container is-Inline">  
  <div class="Center-Block">  
    <!-- CONTENT -->  
  </div>  
</div>  
<Style>

.Center-Container.is-Inline {   
  text-align: center;  
  overflow: auto;  
}  
  
.Center-Container.is-Inline:after,  
.is-Inline .Center-Block {  
  display: inline-block;  
  vertical-align: middle;  
}  
  
.Center-Container.is-Inline:after {  
  content: '';  
  height: 100%;  
  margin-left: -0.25em; /* To offset spacing. May vary by font */  
}  
  
.is-Inline .Center-Block {  
  max-width: 99%; /* Prevents issues with long content causes the content block to be pushed to the top */  
  /* max-width: calc(100% - 0.25em) /* Only for IE9+ */   
}  
</style>

也沒什么好說的,看代碼基本秒懂的級別.通過加一個翻看公司的項目,好像帶我的老哥使用的就是這種辦法.

但是我個人不喜歡這種方法.

先不說CSS寫的又長又臭,在我看來這完全就是一種Hack,需要死記硬背且難以理解.如果有的選擇,我不會選擇這種方法.

3.基于絕對定位的解決方案.

這是一個古老的方法,具體有多古老?大概是在2013年4月6日.(鏈接至StackOverFlow)網(wǎng)上已經(jīng)有了不少考古學(xué)家做了考證,我就不深挖了.它要求元素具有固定的寬度和高度.

<style>
    main{
        position:absolute; /*絕對定位*/
        top: 50%;/*向下移動父元素高度一半*/
        left:50%;/*向右移動父元素寬度一半*/
        margin-top: -3em;/*1em為相對于父元素font-size的100%,-3em為向上移動6/2=3em*/
        margin-left: -9em;
        width: 18em;
        height: 6em;
    }
</style>
<body>
<main>
    <h1>A quick brown fox jump over the lazy dog</h1>
</main>
</body

效果嘛...


title

可以看到,可以幾乎完美的實現(xiàn)垂直居中.它的原理可以這么解釋:

  1. top: 50%;
    left:50%;
    通過這個操作,我們將要添加的元素的左上角固定在了屏幕的正中間.
  2. margin-top: -3em;
    margin-left: -9em;
    因為知道元素的大小,我們用它的一半作為移動值,將元素進行了移動.

等等,這樣寫好像有點累贅.讓我們用calc()改一下.

<style>
    main{
        position:absolute; /*絕對定位*/
        top: calc(50%-3em);/*向下移動父元素高度一半*/
        left:calc(50%-9em)/*向右移動父元素寬度一半*/
        width: 18em;
        height: 6em;
    }
</style>
<body>
<main>
    <h1>A quick brown fox jump over the lazy dog</h1>
</main>
</body>

這樣就明顯好得多了.

這種做法看起來在大多數(shù)情況下都可以滿足需求了.但是它有一個很大的局限性,就是我們需要計算偏移的量,這意味著我們必須知道這個元素多大.想到了什么沒有?對啊,CSS為啥沒有This?如果有This的話,這種問題就根本不是問題了.但是很遺憾的是,這個真沒有.

等等,那就沒有辦法了?

不,為什么說后端學(xué)不會CSS呢?因為CSS是一個很.....神奇的東西.我們在translate()這個八竿子打不著的屬性上居然找到了解決方法.translate()就是以自己本身為目標(biāo)進行變換.查查API,略微思考以后,我們可以很輕易的寫出這樣的方法:

 <style>
    main{
        position:absolute; /*絕對定位*/
        top: 50%;/*向下移動父元素高度一半*/
        left:50%;/*向右移動父元素寬度一半*/
        transform: translate(-50%,-50%);
    }
</style>
<body>
<main>
    <h1>A quick brown fox jump over the lazy dog</h1>
</main>
</body>

這樣就沒什么問題了.
但是缺點還是存在的.首先當(dāng)然是絕對定位的問題,老司機教導(dǎo)我們,能不用絕對定位盡量不要用絕對定位,不然布局出問題了調(diào)試起來很麻煩.然后嘛,就是這樣的問題:

假如元素的高度超過了View層大小,怎么辦?

比如這樣:


title

title

可以很明顯的看到,有一半的文字因為超出大小被裁掉了.這可不好玩.

另外,這種寫法我也認為是一種Hack.如果在確定絕對定位可用且方便的情況下,我也許會用它.

4.使用VH?一個不錯的主意.

我想使用translate()來移動元素進行定位.但是我不想用絕對定位,因為絕對定位是邪惡的.

這個問題很值得思考,那么如何在不用絕對定位的前提下進行定位呢?

我知道有朋友可能要搶答了:"用margin啊,我margin一個50%,不就實現(xiàn)居中了?弄這么多破事干啥?"
很遺憾,這是不行的.

<style>
    main{
        width: 10em;
        padding: 1em 1em;
        margin: 50% auto 0;
        transform: translateY(-50%);
    }
</style>
<body>
<main>
    <h1>A quick brown fox jump over the lazy dog</h1>
</main>
title

這令人窒息的效果!令人窒息的滾動條!

深究其原因,margin的百分比是以父元素的寬度作為解析基準(zhǔn)的.等等,父元素的寬度?那我用margin-top,margin-bottom怎么算?難道是不父元素的高度?

很遺憾,還是父元素的寬度為基準(zhǔn).這就可以說是相當(dāng)?shù)目拥?

那就沒有辦法了嗎?不,現(xiàn)在我們有了CSS3,我們有了VH/VW!1VH相當(dāng)于視口高度的1%,1VW相當(dāng)于視口寬度的1%,完美!再也不用擔(dān)心兼容大小屏幕啦!

在這里例子中如果我們使用VH單位:

<style>
    main{
        width: 10em;
        padding: 1em 1em;
        margin: 50vh auto 0;
        transform: translateY(-50%);
    }
</style>
<body>
<main>
    <h1>A quick brown fox jump over the lazy dog</h1>
</main>
</body>

完美的效果.


title

這個方法我認為沒有缺點.但是適用性一般,畢竟只能應(yīng)用于需要視口居中的頁面

5.在座的各位都是垃圾-byFlex

終于講到每天都在用的東西了.一個不會用Flex的前端,真是太可怕了.
我們只需要給父元素聲明display:flex,再給這個元素在設(shè)置margin:auto,就可以做到垂直居中了.

<style>
    body{
        display: flex;
        min-height: 100vh;
        margin: 0;
    }
    main{
        margin: auto;
    }
</style>
<body>
<main>
    <h1>A quick brown fox jump over the lazy dog</h1>
</main>
title

什么你問我兼容性?


title

97.19%的兼容性,你還有什么不滿意的?簡單粗暴高效.

但是它真的完美嗎?不見得.

仔細看圖不難發(fā)現(xiàn),在你設(shè)置margin-auto之后,不只是垂直,水平也進行了居中.雖然我們可以用

 main{
        margin:auto 0 auto 0;
        /*等同于margin-top: auto;margin-bottom: auto;*/
        
    }

這樣的寫法讓元素實現(xiàn)只垂直居中,但是畢竟又多考慮了兩個屬性.就沒有更好的辦法了嗎?

5.plus,新的曙光.align-self.

于是我們有了更殘暴的align-self(鏈接至MDN)這一屬性.

它讓垂直居中從圣杯變成了隨便寫寫的東西.

我們只需要:
main{
align-self:center;
}
就能夠徹底實現(xiàn)上面margin來margin去的效果.

總結(jié)的比較粗淺,所幸沒有留下什么疑問.這個周末也過得非常充實,以后再碰到垂直居中的問題再也不會去搜啦!

我的blog是blog.codermagefox.com 歡迎來看看!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末末患,一起剝皮案震驚了整個濱河市钉寝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斑响,老刑警劉巖碳蛋,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異厂僧,居然都是意外死亡怜校,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門鹰贵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晴氨,“玉大人,你說我怎么就攤上這事砾莱∪鹂穑” “怎么了凄鼻?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵腊瑟,是天一觀的道長。 經(jīng)常有香客問我块蚌,道長闰非,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任峭范,我火速辦了婚禮财松,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纱控。我一直安慰自己辆毡,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布甜害。 她就那樣靜靜地躺著舶掖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尔店。 梳的紋絲不亂的頭發(fā)上眨攘,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天主慰,我揣著相機與錄音,去河邊找鬼鲫售。 笑死共螺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的情竹。 我是一名探鬼主播藐不,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鲤妥!你這毒婦竟也來了佳吞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤棉安,失蹤者是張志新(化名)和其女友劉穎底扳,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贡耽,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡衷模,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒲赂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阱冶。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖滥嘴,靈堂內(nèi)的尸體忽然破棺而出木蹬,到底是詐尸還是另有隱情,我是刑警寧澤若皱,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布镊叁,位于F島的核電站,受9級特大地震影響走触,放射性物質(zhì)發(fā)生泄漏晦譬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一互广、第九天 我趴在偏房一處隱蔽的房頂上張望敛腌。 院中可真熱鬧,春花似錦惫皱、人聲如沸像樊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽生棍。三九已至,卻和暖如春扫皱,著一層夾襖步出監(jiān)牢的瞬間足绅,已是汗流浹背捷绑。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留氢妈,地道東北人粹污。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像首量,于是被迫代替她去往敵國和親壮吩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容