CSS 实现元素垂直居中
44 年前人类就已经登上了月球,但现在我们仍然无法在 CSS 中实现垂直居中。
在 CSS 中实现一个元素的水平居中很简单:
若是一个行内元素,就对它的父级 text-align: center 即可
若是一个块级元素,就对它本身 margin : auto 即可
然而如果要对一个元素进行垂直居中,就没有简单的方式可以使用,对于尺寸不固定的元素来说尤甚
固定尺寸元素的解决方式
首先给出我们的初始布局例子:
下面给出灰色区块 div 的 css 样式:
1 | main { |
此处灰色区块 div 的宽度是 350px,高度是 150px,我们对该 DIV 进行垂直居中操作
基于绝对定位的解决方案
思路:我们可以把元素本身进行绝对定位,然后把 left 和 top 的值都设置成 50%,把元素的左上角放置在视口(或最近的、具有定位元素的祖先元素)中心,再利用负外边距,将它向左,向上移动(移动距离等于其自身宽高的一半),从而把元素的正中心放置在视口的正中心。
方法 1 ( 元素有确定宽高 ):
代码如下:
1 | main { |
借助 calc() 函数,我们还能把 css 简写成:
1 | main { |
效果图如下:
缺陷:此方法需要知道元素的宽高,但是在实际的应用场景中,其尺寸往往是由其内容决定的,此方法的应用场景就大大受到了限制
方法2 ( 元素没有固定宽高 )
对于没有固定宽高的元素,CSS 中的 translate 变形属性使用百分比时,它是按照自身的宽高为基准进行换算和移动的,正好符合我们的需要,代码如下:
1 | main { |
效果如下:
如此,便可让不定宽高的元素实现垂直居中
基于视口单位的解决方案
假如我们不使用绝对定位,仍然可以采用 transform 的技巧达到我们的效果,但是在缺少 left 和 top 属性的情况下,我们如何把元素移动到容器的正中心呢?
也许我们第一反应会使用 margin 的百分比来解决,代码如下:
1 | main { |
结果:
结果出乎我们的预料,原因在于,margin 的百分比值是以其父元素的宽度作为解析基准的,无论是 margin-top、margin-bottom、margin-left 或是 margin-right 都一样。不过要是我们只是想让一个元素垂直居中,还是有路可走的。 CSS 定义了一套与视口相关的长度单位 vh 和 vw 。
vh 的定义:
相对于视口的高度,视口被均分为 100 单位的 vh
1 vh 代表了 1% 的视口高度
视口指的是浏览器的可视区部分(innerWidth 和 innerHeight 的范围),不包含浏览器的导航栏和标签栏之类。
vw 的定义:
相对于视口的宽度,视口被均分为 100 单位的 vw
1 vw 代表了 1% 的视宽高度
vh 的兼容性:
vw 的兼容性:
可见移动端基本都支持,兼容性方面并不需要过多的担心,唯一例外的就是 uc 浏览器,全系列不支持,若是需要兼容 uc mobile 需要慎重考虑,代码如下:
1 | main { |
效果如下:
基于 Flexbox 的解决方案
伸缩盒模型 flexbox 是解决此类问题最理想的方式,它就是为此而设计的,之前的浏览器由于兼容性问题,这种方式不是很推荐,但目前该特性的支持度已经不需要太过担心,以下是兼容性列表:
可见 IE9 以上都支持。
实现代码如下( 1 ):
父级:
1 | body { |
子级:
1 | main { |
此处需要注意的是:
- 父级需要指定高度,这里设置成了 100vh, 也就是整个视口的高度
- 子级的 margin: auto 不仅在垂直方向上让元素垂直居中,在水平方向上也一样
实现代码如下( 2 ):
父级:
1 | body { |
效果如下:
justify-content 用于设置主轴 (横轴) 上的对齐方式
align-items 用于设置侧轴(纵轴)上的对其方式
表格布局法实现垂直居中
表格中的内容只要设置了 vertical-align: middle 时,内容便会垂直居中,只是这种方式局限性大, hack 的味道过重,代码如下:
html 结构:
1 | <div class="wrapper"> |
父级 CSS:
1 | .wrapper { |
子级 CSS:
1 | .content { |
效果:
这里为了方便演示,把父级的高度设置成了 100%,实际生产场景中按照需要设置即可,这里面用 display:table 代替 table 标签,方便大家按照习惯来书写。
行内块法实现垂直居中
我们可以使用一个伪元素,用于撑开容器的高度,实现垂直居中。
html 结构:
1 | <div class="block" style="height: 600px;"> |
css 代码:
1 | .block { |
效果:
此处我们可以定一个 inline-block 类型的伪元素,然后让它的高度设置为 100%,并且让它按照中线居中,即可让内部同为 inline-block 的元素垂直居中。此方法只适用于 inline-block 元素,局限性较大。
基于自适应绝对定位的解决方法
之前介绍的绝对定位法,无论元素是否具有固定的宽高,我们都会想办法把元素左上角拉到视口的中心,现在介绍一种不需要把把元素拉到视口中心的方法
html 结构:
1 | <div class="wrapper"> |
CSS:
1 | .wrapper { |
步骤:
- 给子级元素设置绝对定位 position: absolute
- 子级设置 margin: auto
- 子级设置 top: 0; right: 0; bottom: 0; left: 0
效果图:
如此便实现了垂直居中