刚参加工作时被面试官一连串居中问题虐的体无完肤得场景历历在目:
问到后面脑子里一团浆糊,本来知道的也不知道该如何回答了。居中是日常工作中不可避免要遇到的场景,面试中也是高频出现。这次的文章就围绕这些问题展开,希望能够帮助有和我当年一样疑惑的同学,在今后的工作和面试中再面对居中问题的时候可以游刃有余。
单行文本的垂直居中是最简单的,设置 line-height 与盒子高度一样就可以。
这里有一个误区,很多人设置单行文本居中的时候会同时设置 height 与 line-height 相同,其实大可不必设置 height , 只设置 line-height 就可以,这时候盒子的高度由 line-height 撑起来,与 line-height 完全相同。
.center {
// 完全可以不设置高度
// height: 20px;
line-height: 20px;
}

vertical-align 可以指定行内元素的垂直对齐方式。
这个方法需要多增加一个 .center 元素将需要居中的内容包裹起来。设置父元素的 line-height 为元素的高度,居中子元素 .center 的 display 为 inline-block ,使其拥有行内元素的特性,因为 line-height 的继承性,所以设置 line-height: 20px; 重置居中子元素的 line-height ,然后设置 vertical-align: middle; 在行框盒子内垂直居中对齐。
<div class="box">
<div class="center">
虽然你们是扮演路人甲乙丙丁,但是一样是有生命、有灵魂的。
</div>
</div>
<style>
.box {
background-color: orange;
line-height: 200px;
width: 300px;
}
.center {
background-color: green;
line-height: 20px;
display: inline-block;
vertical-align: middle;
}
</style>
不同于行内元素设置利用 vertial-align 会使当前元素垂直居中对齐, table-cell 元素设置 vertial-align 会让它的子元素垂直居中对齐,就算子元素是块级元素也会垂直对齐,所以想要实现块级元素的垂直居中也可以使用这个方法。
.box {
height: 200px;
display: table-cell;
vertical-align: middle;
}
text-align 控制子行内元素的水平对齐方式,这个非常简单直接设置 text-align:center 就可以。
.center {
text-align: center;
}
margin 的值为 auto 可以占据对应方向的所有剩余空间,如果设置水平方向上两个方向的 margin 值都为 auto ,两个方向就会平分剩余空间,从而实现居中。
那么为什么我们从来没有使用这个方法来实现垂直方向的居中呢?因为 auto 值起作用有一个前置条件,就是在对应的方向上如果不设置具体的长度,会自动铺满。很显然 width 是可以铺满父元素的,而 height 不可以。
.center {
margin: 0 auto;
}
那可不可以利用 margin:auto; 实现垂直方向的居中呢?当然可以,可以通过修改 writing-mode 改变块的流动,使块横向流动,此时 height 方向就会默认平铺撑满,设置 margin:auto; 就可以实现垂直方向的居中。但是这个方法有副作用,因为 writing-mode 属性的可继承性,会导致该元素下得所有子元素全部流方向全部变为横向。而且此时水平方向不能再使用此方法实现居中了。
<div class="box">
<div class="center">
虽然你们是扮演路人甲乙丙丁,但是一样是有生命、有灵魂的。
</div>
</div>
<style>
.box {
background-color: orange;
height: 200px;
writing-mode: vertical-lr;;
}
.center {
background-color: green;
height: 50px;
margin: auto 0;
}
</style>
那有没有可能使用这个特性实现垂直与水平方向都居中呢?也是可以得,我们继续往下看
设置父元素绝对定位,居中元素相对定位, top 、 right 、 bottom 、 left 的值都为 0,此时如果不设置具体的宽高,居中元素就会在水平和垂直两个方向都铺满父元素。此时再给它设置具体宽高配合 margin:auto; 就可以实现绝对居中了。
需要注意的是这个方法只能兼容 IE8 及以上浏览器,如果项目要兼容 IE7 可以使用下面这种方法
.box {
position: relative;
}
.center {
position:absolute;
width: 200px;
height: 200px;
top:0;
bottom:0;
left:0;
right:0;
margin: auto;
}
首先实现居中元素在水平方向上的居中,设置居中元素的 display 值为 inline-clock ,使其拥有行内元素的特性。给外层的盒元素设置 text-align: center; 使居中元素在水平方向上居中。
然后再实现在垂直方向上的居中,这个方法需要添加一个辅助元素,设置辅助元素 height:100%; 使当前行框盒子的高度撑满父元素,然后设置 vertical-align: middle; 使其在垂直方向上居中对齐。
<div class="box">
<div class="assist"></div>
<div class="center">
虽然你们是扮演路人甲乙丙丁,但是一样是有生命、有灵魂的。
</div>
</div>
<style>
.box {
background-color: orange;
height: 200px;
width: 500px;
text-align: center;
}
.center {
background-color: green;
width: 150px;
display: inline-block;
vertical-align: middle;
}
.assist {
display: inline-block;
height: 100%;
vertical-align: middle;
}
</style>
这个方法适用与居中元素宽高已知的情况。设置父元素相对定位,居中元素绝对定位, left 、 top 值都为 50%, left 、 top 的值分别相对于父元素的宽高计算,此时居中元素的左上顶点会位于父元素的正中央。然后再设置居中元素的 margin-left 、 margin-top 为宽高的负一半,让居中元素在水平方向相对于自身宽度的 50% 向左偏移,在垂直方向向上偏移相对于自身高度的 50%,就可以实现居中效果了。
<div class="box">
<div class="center">
虽然你们是扮演路人甲乙丙丁,但是一样是有生命、有灵魂的。
</div>
</div>
<style>
.box {
background-color: orange;
height: 200px;
width: 500px;
position: relative;
}
.center {
background-color: green;
width: 150px;
height: 50px;
position:absolute;
top:50%;
left:50%;
margin-left: -75px;
margin-top: -25px;
}
</style>
第四种方法是使用 position 配合 transform 。这种方法跟上一个方法原理上基本相似,但使用场景增加了宽高不固定的元素。一样的先设置父元素相对定位,居中元素绝对定位, left 、 top 值都为 50%。再设置居中元素 transform: traslate(-50%, -50%); , translate 的百分比值是相对于自身去计算的,让居中元素在水平方向相对于自身宽度的 50% 向左偏移,在垂直方向向上偏移相对于自身高度的 50%,就可以实现居中效果了。
<div class="box">
<div class="center">
虽然你们是扮演路人甲乙丙丁,但是一样是有生命、有灵魂的。
</div>
</div>
<style>
.box {
background-color: orange;
height: 200px;
width: 500px;
position: relative;
}
.center {
background-color: green;
width: 150px;
position:absolute;
top:50%;
left:50%;
transform: traslate(-50%, -50%);
}
</style>
如果不需要考虑兼容 IE9 及以前的浏览器, flex 布局是最推荐的方式。
设置父元素为 flex 容器,主轴、交叉轴对齐方式都为居中对。关于 flex 的相关知识可以参考转自阮大神的文章,介绍的非常详细。
.box {
display: flex;
align-items: center;
justify-content: center;
}
