【CSS trick】垂直居中

我们都知道,通过margin: 0 auto;,可以很简单的就实现了水平居中,但是我们却不能通过margin: auto;来实现垂直居中。要在各种环境下实现完美居中,还是一件挺烦人的事情,特别对于新人来说。虽然通过google我们可以很方便的找到一种实现方式,但是如果只会使用而不了解其实现原理的话,是非常不利于我们学习的。下面我们就来一一探索常见的6种实现方式的奥秘。

首先,我们先来整体对比下6中实现方式

Center

Absolute-Center

css
1
2
3
4
5
.Absolute-Center {
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}

下面分析这种方式的内容原理

在普通的内容流中,margin: auto;的效果相当于topbottom均为0,也即margin-top或者margin-bottom 设为auto的时候,它们的值其实就是0。

W3.org: If ‘margin-top’, or ‘margin-bottom’ are ‘auto’, their used value is 0.

当设置position: absolute;,离开了普通的内容流之后,就不一样了。

对于绝对布局的元素,它的top, right, bottom, and left属性,是用来指定与外部容器(相对布局的父元素或者body)边缘的偏移值。当元素的高度和宽度已知,则浏览器会将margin-topmargin-bottom设置成一样,因此元素就居中了。

优势

  • 浏览器兼容性
  • 不需要增加额外的元素来布局

不足

  • 需要指定高度(可以使用百分比%属性来部分支持可变的高度)

Negative Margins

如果我们事先能够确认元素的大小,并且元素的大小是固定的,那我们只需要设置元素的topleft均等于父元素的50%,然后设置margin-topmargin-left为元素高度和宽度的负一半就可以实现居中:

css
1
2
3
4
5
6
7
{
position: absolute;
left: 50%;
top: 50%;
margin-left: -285px;
margin-top: -190px;
}

原理

设置leftright将元素的左上角放置在容器中心,然后设置margin-leftmargin-top等于元素宽度和高度的50%,便可以将元素的中心移到容器的中心。

优势

  • 只需要少量代码就可实现
  • 浏览器兼容性好

不足

  • 不支持可变的高度
  • 需要手动计算偏移值

Transforms

实现方式与Negative Margins方式非常相似,只是通过transform来实现偏移

css
1
2
3
4
5
6
7
8
9
{
position: absolute;
top: 50%;
left: 50%;
margin: auto;
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}

原理

使用transform来控制元素的偏移

优势

  • 支持可变的高度
  • 少量代码就可实现

劣势

  • IE8及以下不支持
  • 需要添加浏览器引擎前缀
  • 因为设置了transform,可能会影响到其他转换
  • 一些情况下,边缘或者文字会变得模糊

Table-Cell

Table-Cell这种方式应该是最简单粗暴的方法了

html
1
2
3
4
5
6
7
<table style="width: 100%;">
<tr>
<td style="text-align: center; vertical-align: middle;">
Unknown stuff to be centered.
</td>
</tr>
</table>

由于现在我们会非常关注语言,所有如果要增强语义的话,我们可以用class来替代,然后在css文件中将容器的display为table,子元素的display为table-cell便可

html
1
2
3
4
5
<div class="something-semantic">
<div class="something-else-semantic">
Unknown stuff to be centered.
</div>
</div>
css
1
2
3
4
5
6
7
8
9
10
.something-semantic {
display: table;
width: 100%;
}

.something-else-semantic {
display: table-cell;
text-align: center;
vertical-align: middle;
}

优势

  • 实现简单,容易理解

不足

  • 语义不够明确
  • 需要增加额外元素

Inline-Block

html
1
2
3
4
5
<div class="Center-Container">
<div class="Center-Block">
<!-- CONTENT -->
</div>
</div>
css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.Center-Container {
text-align: center;
overflow: auto;
}

.Center-Container:after,
.Center-Container .Center-Block {
display: inline-block;
vertical-align: middle;
}

.Center-Container:after {
content: '';
height: 100%;
margin-left: -0.25em; /* To offset spacing. May vary by font */
}

.Center-Container .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+ */
}

原理

1)当元素设置了text-align:center;,那么其内部text元素都会水平居中,这些元素包括inline-block的元素;
2)通过使用伪类after,并且设置了height: 100%;vertical-align: middle;,这样所有与它垂直对齐的元素都会与它中心对齐,也即在容器中垂直居中。

优势

  • 支持可变高度的内容
  • 浏览器兼容性好,能够直接IE7

不足

  • 需要增加额外元素
  • 不是很好理解
  • 依赖于margin-left: -0.25em;来实现水平居中,对于不同的字体,可能需要进行微调。
  • 放置内容的容器的大小必须不能超过外部容器的宽度减去0.25em

FlexBox

Flexible Box,简称Flex,意为”弹性布局”,用来为盒状模型提供最大的灵活性。这里不过多介绍Flex,希望了解更多的同学,可以参考这篇博客A Complete Guide to Flexbos

css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.Center-Container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-moz-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}

优势

  • 支持任意宽度或高度的内容
  • 更为灵活的布局方式

不足

  • IE8-9不支持
  • 需要外部容器或者修改body的样式
  • 需要添加浏览器引擎前缀