事實上紧唱,每次面試前端必問的問題就是這個评甜。及其常見的需求灰粮,看起來似乎非常簡單,但是實現(xiàn)起來很費勁忍坷,尤其是涉及尺寸不固定的元素粘舟。
本篇文章將介紹比較流行的幾種方法熔脂。
行內(nèi)塊
<body>
<div id="ghost"></div>
<span>
hello
</span>
</body>
#ghost {
display: inline-block;
height: 20em;
vertical-align: middle;
}
本質(zhì)上是利用了內(nèi)聯(lián)元素的 vertical-align 屬性,通過將此屬性置為middle柑肴,同一行內(nèi)的內(nèi)聯(lián)元素都將以設置這一屬性的內(nèi)聯(lián)元素的基線對齊霞揉。
基于inline-block特有的屬性:擁有內(nèi)聯(lián)元素的特性同時可以定義寬高,我們可以設置一個ghost行內(nèi)塊用于定義高度晰骑,再讓其他內(nèi)聯(lián)元素與其對齊零聚,實現(xiàn)垂直居中。
當然我們也可以將其它元素置為行內(nèi)塊些侍,再設置寬度并添加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()函數(shù)可以說明得更加清楚:
#child {
position: absolute;
top: calc(50%-5em);
left: calc(50%-5em);
height: 10em;
width: 10em;
}
不固定寬高
實際中大多數(shù)時候我們并不知道子元素的實際寬高胁住。
如果你屬性translate()函數(shù),你一定知道當它的參數(shù)為百分比時刊咳,它會按照元素本身的百分比值進行變換彪见,我們可以通過這個方法徹底擺脫對尺寸的依賴!
#child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
看起來已經(jīng)完美解決了娱挨,但是它還有以下的缺陷:
- 絕對定位會對整體的布局造成很強烈的影響余指。
- 如果居中的元素超過了視窗會被裁剪掉。
- 在某些瀏覽器中跷坝,元素可能會被放置在半個像素上造成模糊酵镜。
視口居中
如果我們不采用絕對定位,對子元素設置margin使其左上角置于父元素中點柴钻,再用translate重復上一種方法的操作淮韭,是否可以實現(xiàn)呢?
答案是不可以贴届,因為margin的百分比是以父元素的寬度為基準的靠粪,即便是top和bottom也是! 沒錯毫蚓,很扯占键。
如果僅僅想要垂直于視口,我們可以采用css中相對于視口的單位 vw绍些、vh捞慌、vmin耀鸦、vmax
- 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的話择同,其實還有多種實現(xiàn)方式。
body {
display: flex;
justify-content: center;
align-items:center;
}
或者對子元素單獨設置交叉軸對齊方式:
body {
display: flex;
justify-content: center;
}
#main {
align-self:center;
}