作為一個(gè)切圖的頁面仔,工作中總是要用到垂直居中.忙的時(shí)候一般就隨便google一個(gè)復(fù)制粘貼上去,也從來沒有思考過內(nèi)在的聯(lián)系與原因,但是今天晚上聽聽音樂想看看書的時(shí)候,突然心血來潮.擇日不如撞日,就今天吧,夯實(shí)一下我的基礎(chǔ),從此讓所有垂直居中都變成紙老虎!!!
那么,先談?wù)労?jiǎn)單的垂直居中吧.
在CSS中想要實(shí)現(xiàn)水平居中可以說是十分簡(jiǎn)單了,行內(nèi)元素用text-align:center,塊級(jí)元素用margin:auto,元素就會(huì)乖乖的自己跑到元素水平中間去.
但是這么多年下來,垂直居中已經(jīng)成為了CSS領(lǐng)域的圣杯.
可以說,一個(gè)不能解決這個(gè)問題的人簡(jiǎn)直是寸步難行.不管你想做一個(gè)怎樣的網(wǎng)頁,垂直居中都有很大的可能性會(huì)用到.但是,它并不簡(jiǎn)單,甚至可以說難于登天.
為了解決這個(gè)絕世難題,前端開發(fā)者們從各個(gè)方面想出了各種不同的點(diǎn)子.之前也許你在百度的某個(gè)角落里找到過一些碎片,今天我嘗試將這些碎片組裝起來,還原一個(gè)真正的垂直居中,也將自己的基礎(chǔ)進(jìn)行一次夯實(shí).
1.表格布局法.
第一個(gè)想到表格布局法的人已經(jīng)無法考證,但是不得不說這真的是一個(gè)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>
寫一個(gè)表格,將需要居中顯示的內(nèi)容放在表格正中間.自適應(yīng),內(nèi)容變方塊大小也跟著變,兼容性更是不得了.
97.72%.基本沒有不能兼容的.
嗯,所以應(yīng)該說:
表格布局法的優(yōu)點(diǎn)就是兼容性及其變態(tài),基本沒有不能兼容的.缺點(diǎn)也很明顯,需要添加冗余的HTML樣式,這在網(wǎng)頁開發(fā)中一般是不能被接受的.而且display:table有極大的可能性會(huì)擾亂整個(gè)頁面的布局,使用這種方法還是有一定風(fēng)險(xiǎn)的.
2.行內(nèi)塊法.
這個(gè)方法的本質(zhì)是使用
display: inline-block;
vertical-align: middle;
讓一個(gè)偽元素居于容器中央.
<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>
也沒什么好說的,看代碼基本秒懂的級(jí)別.通過加一個(gè)翻看公司的項(xiàng)目,好像帶我的老哥使用的就是這種辦法.
但是我個(gè)人不喜歡這種方法.
先不說CSS寫的又長(zhǎng)又臭,在我看來這完全就是一種Hack,需要死記硬背且難以理解.如果有的選擇,我不會(huì)選擇這種方法.
3.基于絕對(duì)定位的解決方案.
這是一個(gè)古老的方法,具體有多古老?大概是在2013年4月6日.(鏈接至StackOverFlow)網(wǎng)上已經(jīng)有了不少考古學(xué)家做了考證,我就不深挖了.它要求元素具有固定的寬度和高度.
<style>
main{
position:absolute; /*絕對(duì)定位*/
top: 50%;/*向下移動(dòng)父元素高度一半*/
left:50%;/*向右移動(dòng)父元素寬度一半*/
margin-top: -3em;/*1em為相對(duì)于父元素font-size的100%,-3em為向上移動(dòng)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
效果嘛...
可以看到,可以幾乎完美的實(shí)現(xiàn)垂直居中.它的原理可以這么解釋:
- top: 50%;
left:50%;
通過這個(gè)操作,我們將要添加的元素的左上角固定在了屏幕的正中間. - margin-top: -3em;
margin-left: -9em;
因?yàn)橹涝氐拇笮?我們用它的一半作為移動(dòng)值,將元素進(jìn)行了移動(dòng).
等等,這樣寫好像有點(diǎn)累贅.讓我們用calc()改一下.
<style>
main{
position:absolute; /*絕對(duì)定位*/
top: calc(50%-3em);/*向下移動(dòng)父元素高度一半*/
left:calc(50%-9em)/*向右移動(dòng)父元素寬度一半*/
width: 18em;
height: 6em;
}
</style>
<body>
<main>
<h1>A quick brown fox jump over the lazy dog</h1>
</main>
</body>
這樣就明顯好得多了.
這種做法看起來在大多數(shù)情況下都可以滿足需求了.但是它有一個(gè)很大的局限性,就是我們需要計(jì)算偏移的量,這意味著我們必須知道這個(gè)元素多大.想到了什么沒有?對(duì)啊,CSS為啥沒有This?如果有This的話,這種問題就根本不是問題了.但是很遺憾的是,這個(gè)真沒有.
等等,那就沒有辦法了?
不,為什么說后端學(xué)不會(huì)CSS呢?因?yàn)镃SS是一個(gè)很.....神奇的東西.我們?cè)趖ranslate()這個(gè)八竿子打不著的屬性上居然找到了解決方法.translate()就是以自己本身為目標(biāo)進(jìn)行變換.查查API,略微思考以后,我們可以很輕易的寫出這樣的方法:
<style>
main{
position:absolute; /*絕對(duì)定位*/
top: 50%;/*向下移動(dòng)父元素高度一半*/
left:50%;/*向右移動(dòng)父元素寬度一半*/
transform: translate(-50%,-50%);
}
</style>
<body>
<main>
<h1>A quick brown fox jump over the lazy dog</h1>
</main>
</body>
這樣就沒什么問題了.
但是缺點(diǎn)還是存在的.首先當(dāng)然是絕對(duì)定位的問題,老司機(jī)教導(dǎo)我們,能不用絕對(duì)定位盡量不要用絕對(duì)定位,不然布局出問題了調(diào)試起來很麻煩.然后嘛,就是這樣的問題:
假如元素的高度超過了View層大小,怎么辦?
比如這樣:
可以很明顯的看到,有一半的文字因?yàn)槌龃笮”徊玫袅?這可不好玩.
另外,這種寫法我也認(rèn)為是一種Hack.如果在確定絕對(duì)定位可用且方便的情況下,我也許會(huì)用它.
4.使用VH?一個(gè)不錯(cuò)的主意.
我想使用translate()來移動(dòng)元素進(jìn)行定位.但是我不想用絕對(duì)定位,因?yàn)榻^對(duì)定位是邪惡的.
這個(gè)問題很值得思考,那么如何在不用絕對(duì)定位的前提下進(jìn)行定位呢?
我知道有朋友可能要搶答了:"用margin啊,我margin一個(gè)50%,不就實(shí)現(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>
這令人窒息的效果!令人窒息的滾動(dòng)條!
深究其原因,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>
完美的效果.
這個(gè)方法我認(rèn)為沒有缺點(diǎn).但是適用性一般,畢竟只能應(yīng)用于需要視口居中的頁面
5.在座的各位都是垃圾-byFlex
終于講到每天都在用的東西了.一個(gè)不會(huì)用Flex的前端,真是太可怕了.
我們只需要給父元素聲明display:flex,再給這個(gè)元素在設(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>
什么你問我兼容性?
97.19%的兼容性,你還有什么不滿意的?簡(jiǎn)單粗暴高效.
但是它真的完美嗎?不見得.
仔細(xì)看圖不難發(fā)現(xiàn),在你設(shè)置margin-auto之后,不只是垂直,水平也進(jìn)行了居中.雖然我們可以用
main{
margin:auto 0 auto 0;
/*等同于margin-top: auto;margin-bottom: auto;*/
}
這樣的寫法讓元素實(shí)現(xiàn)只垂直居中,但是畢竟又多考慮了兩個(gè)屬性.就沒有更好的辦法了嗎?
5.plus,新的曙光.align-self.
于是我們有了更殘暴的align-self(鏈接至MDN)這一屬性.
它讓垂直居中從圣杯變成了隨便寫寫的東西.
我們只需要:
main{
align-self:center;
}
就能夠徹底實(shí)現(xiàn)上面margin來margin去的效果.
總結(jié)的比較粗淺,所幸沒有留下什么疑問.這個(gè)周末也過得非常充實(shí),以后再碰到垂直居中的問題再也不會(huì)去搜啦!
我的blog是blog.codermagefox.com 歡迎來看看!