准备代码:
<!--html-->
<main>
<h1>Am I centered yet?</h1>
<p>Center me, please!</p>
</main>
/*css*/
*{
margin:0
}
main{
background:#FFF000;
padding:10px;
text-align:center;
}
初始效果如图1:
图1
一.绝对定位解决方案
main {
position: absolute;
top: 50%;
left: 50%;
margin-top: -3em; /* 6/2 = 3 */
margin-left: -9em; /* 18/2 = 9 */
width: 18em;
height: 6em;
}
此解决方案的思路是,距离左上角绝对定位,top
和left
各50%,然后再负值定位自身的一半的宽度和高度,也可以使用calc()
简化代码,效果如图2
main {
position: absolute;
top: calc(50% - 3em);
left: calc(50% - 9em);
width: 18em;
height: 6em;
}
图2
很显然,这里最大的问题是需要被定位的元素有固定的大小,然而大部分情况下被垂直居中的元素都是跟随其内容的大小。如果我们有一种方法来使用解析到元素的百分比,我们的问题就会得到解决!但是大多数的CSS属性(包括margin),比例都依赖于他们的父元素。但是当我们把比例用在
translate()
时,我们移动元素是基于他自身的宽度和高度,这正是我们所需要的,实现效果如图3:
main {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
图3
但此技术有些使用警告:
- 绝对定位通常不是一个好的选项,因为它对整个布局的影响相当激烈
- 如果要居中的元素比视口高,就会剪切其顶部(图4)。
- 在一些浏览器上,会导致元素出现轻微的模糊,因为他们被放在一半像素上(可以通过
transform-style: preserve-3d
来解决,但不能保证以后会不会被支持)
图4
二.视口单位(viewport unit)解决方案
假设我们避开使用绝对定位,我们仍然可以使用他translate()
讲元素的宽度和高度移动自身一半的技巧,但是我们如何不使用left
和top
将元素放到中间呢,我们第一个想到的是用margin
属性:
main {
width: 18em;
padding: 1em 1.5em;
margin: 50% auto 0;
transform: translateY(-50%);
}
图5
然而我们确得到图5的结果,因为
margin
属性的‘比例’是基于父级的宽度,幸好,让一个元素在视口居中还是可以的,CSS3定义了新的长度单位家族,叫做viewport-relative length:
-
vw
基于视口的宽度,与大多数期望的不同,1vw
代表视口宽度的1%而不是100% - 和
vm
相似,1vh
代表视口高度的1% -
1vmin
相对于视口的宽度或高度中较小的那个。 -
1vmax
相对于视口的宽度或高度中较大的那个。
所以我们可以将代码修改为:
main {
width: 18em;
padding: 1em 1.5em;
margin: 50vh auto 0;
transform: translateY(-50%);
}
三.Flexbox 解决方案
这无疑是最好的解决方案,其他解决方案还在使用的唯一原因是因为他们可以更好的支持浏览器,尽管现在的浏览器对Flexbox的支持也非常好了:
body {
display: flex;
min-height: 100vh;
margin: 0;
}
main {
margin: auto;
}
网友评论