44年前我们把人送上月球,但在CSS中我们仍然不能很好实现垂直居中——@James Anderson
让一个元素水平居中对于CSS来说非常简单:如果是一个内联元素,我们可以在他的父元素上设置text-align:center;
,如果是一个块元素,我们可以使用margin:auto;
。然而,只要一想到让一个元素垂直居中,让人死的心都有了。
多年来,垂直居中已成为CSS的不朽神话,也是前端专业人士群体中的一个内部笑话。原因是:
- 经常需要使用
- 理论上看上去非常简单
- 过去实战中要实现是极其困难,特别是元素大小固定时
方法一:绝对定位
实现过程
1 | <div class="container"> |
1 | .container{ |
方法二:绝对定位+负margin
这或许是最常用的方法。如果知道了各个元素的大小,设置等于宽高一半大小的负margin
值(如果没有使用box-sizing: border-box
样式,还需要加上padding
值),再配合top: 50%
; left: 50%;
样式就会使块元素居中。
给容器设置绝对定位(position:absolute
),并且定位高度(top:50%
)和margin-top
为高度的一半(margin-top:-height/2
),宽度设置类似。
这就意味着使用这种方法来实现垂直居中的效果,那么元素必须要有一个固定的高度。这样一来,给元素设置了固定高度,如果又设置了overflow:auto
,那么当元素内容超过容器后,这样元素的就会出现滚动,而不会自适应内容的高度。
实现过程
1 | <div class="container"> |
1 | .container{ |
如果使用CSS3中的calc()
可以减少两个样式:1
2
3
4
5
6
7
8.center{
height:100px;
width:100px;
position:absolute;
top:calc(50% - 50px);/* calc中的`+` `-` 必须被空格包围,`*` `/` 则不需要*/
left:calc(50% - 50px);
background-color: rgba(255,255,0,1);
}
优点
- 浏览器兼容性非常好,甚至支持IE6-7
- 需要的编码量很少
缺点
- 这是个非响应式的方法,不能使用百分比的大小,也不能设置
min-/max-
的最大值最小值。 - 内容可能会超出容器
- 需要为
padding
预留空间,或者需要使用box-sizing: border-box
样式。
方法三:模拟表格
这种可能是最好的方法,因为高度可以随内容改变,浏览器支持也不差。主要缺陷是会产生额外的标签,每一个需要居中的元素需要三个额外的HTML标签。
实现过程
设置父元素display:table
,子元素display:table-cell; vertical-align:middle
1
2
3
4
5<div class="table">
<div class="table-cell">
<div class="content">完全居中--3.模拟表格</div>
</div>
</div>
1 | .table{ |
优点
- 内容高度可变
- 内容溢出则能自动撑开父元素高度
- 浏览器兼容性好
缺点
- 需要额外的HTML标签
方法四:inline-box
基本方法是使用display: inline-block
,vertical-align: middle
样式和伪元素让内容块在容器中居中。
实现过程
1 | <div class="container"> |
1 | .container{ |
优点
- 内容高度可变
- 内容溢出则能自动撑开父元素高度
- 浏览器兼容性好,甚至可以调整支持IE7
缺点
- 需要额外容器
- 依赖于
margin-left: -0.25em
的样式,做到水平居中,需要为不同的字体大小作调整
内容区声明的宽度不能大于容器的100% 减去0.25em的宽度
方法五:transform(CSS3)
为内容指定带有厂商前缀的transform: translate(-50%,-50%)
和top: 50%; left: 50%;
样式就可以让内容块居中。
实现过程
1 | <div class="container"> |
1 | .container{ |
优点
方法六:flex(CSS3)
CSS未来发展的方向就是采用Flexbox这种设计,解决像垂直居中这种共同的问题。请注意,Flexbox有不止一种办法居中,他也可以用来分栏,并解决奇奇怪怪的布局问题。
实现过程
1 | <div class="container"> |
1 | .container{ |
优点
完全居中对照表
所用样式 | 支持的浏览器 | 是否响应式 | 内容溢出后的样式 | resize:both | 高度可变 | 主要缺陷 |
---|---|---|---|---|---|---|
absolute | 现代浏览器&IE8+ | 是 | 会导致容器溢出 | 是 | 是* | ‘可变高度’的特性不能跨浏览器 |
负margin值 | 所有 | 否 | 带滚动条 | 大小改变后不再居中 | 否 | 不具有响应式特性,margin值必须经过手工计算 |
transform | 现代浏览器&IE9+ | 是 | 会导致容器溢出 | 是 | 是 | 妨碍渲染 |
table-cell | 现代浏览器&IE8+ | 是 | 撑开容器 | 否 | 是 | 会加上多余的标记 |
inline-block | 现代浏览器&IE8+&IE7* | 是 | 撑开容器 | 否 | 是 | 需要使用容器包裹和hack式的样式 |
flex | 现代浏览器&IE10+ | 是 | 会导致容器溢出 | 是 | 是 | 需要使用容器包裹和厂商前缀(vendor prefix) |