Fork me on GitHub

到底怎么样才能水平垂直居中喔

 垂直居中这个问题我觉得是面试里面对CSS考核的最常见的一个问题,并且在实际场景中也应用广泛,有必要拿出来说一说。

使用margin的auto属性

  这种方式有很多变种,但有一点值得我们留意:我们使用margin的auto属性时需要有指定的宽度和高度声明。因为说到底,auto属性还是会根据剩余空间来分配,如果没有给当前盒子指定高宽,那就无法进行计算。

  下面我们的html页面统一body内容如下:

1
2
3
4
<div class="container">
<div class="main">
</div>
</div>

margin: 0 auto , top: 50%, transform: translateY(-50%)

  这种方案是我目前见到比较多的的居中手段,先是将容器水平居中,再根据父级调整到垂直居中,注意这里的main容器需要相对定位才能水平居中,如果使用绝对定位,水平居中将会失效,原因是,这种定位会破坏BFC,即原有的块级上下文结构被破坏,auto就无法再根据之前的父级剩余空间去计算,如果非要用绝对定位,那只能通过正常的定位left: 50%, transform: tranlateX(-50%)来解决该问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
.container {
position: relative;
width: 300px; height:150px;
background: black;
}
.main {
position: relative;
margin: 0 auto;
top: 50%;
transform: translateY(-50%);
width: 200px; height: 100px;
background: blue;
}

margin: auto , top: 0 , right: 0 , bottom: 0 , left: 0

  这种方案是近期发现的,根据张鑫旭老师博客的解释: 当一个绝对定位元素,其对立定位方向属性同时有具体定位数值的时候,流体特性就发生了。那么流体特性是什么,即这个auto属性就会分割剩余空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.container {
position: relative;
width: 300px;
height:150px;
background: black;
}
.main {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
margin: auto;
width: 200px;
height: 100px;
background: blue;
}

flex布局

  弹性布局也是面试里面喜欢问的一个高频样式布局方案,除了这种垂直居中的应用,还有一些什么圣杯啊blabla的,本质就是一个flex。弹性布局实现样式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
.container {
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height:150px;
background: black;
}
.main {
width: 200px;
height: 100px;
background: blue;
}

display: table-cell

  这种方法,主要是能够使用vertical-align: middle的属性。从table-cell的描述而言,它就是让原本的容器表现形式转为table的单元格的形式,而单元格(td)中的内容默认就是vertical-align: middle垂直居中的。所以剩下我们要做的就是将其水平居中,见前文的margin: 0 auto。注:IE8以下不支持display的table系value。

1
2
3
4
5
6
7
8
9
10
11
12
13
.container {
width: 300px;
height: 150px;
background: black;
display: table-cell;
vertical-align: middle;
}
.main {
width: 200px;
height: 100px;
margin: 0 auto;
background: blue;
}

伪元素占位 + display: inline-block

  奇技淫巧,伪元素选择器来占位,由于::before会有一个诡异的占位宽度,所以这里使用::after。注:IE8以下不支持伪类选择器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.container {
width: 300px;
height: 150px;
background: black;
text-align: center;
}

.container::after {
content: "";
display: inline-block;
height: 100%;
/* 这里必须用100% */
vertical-align: middle;
}

.main {
width: 200px;
height: 100px;
/* margin: 0 auto; 无效了*/
background: blue;
display: inline-block;
vertical-align: middle;
}