

CSS 垂直居中
source link: https://lotabout.me/2016/CSS-vertical-center/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

简单一句 margin: 0 auto
我们便能搞定水平居中,而正当我们开心地写出 margin: auto 0
时,浏览器却没却无情地拒绝了我们,那我们来看看如何用 CSS 实现垂直居中吧。
要完全理解本文,我们假设你已经对 CSS 较为熟悉,包括 CSS 盒模型(box model), position 的常用方法,伪元素的使用等等。但若只是工作需要,照抄就是!
本文示例用 Jsfiddle 编辑,可能载入较慢,请耐心等待。
垂直居个中,怎么就这么难
正如前言所说,水平居中,通常只需要一句:margin: 0 auto
即可解决。而同样的方法对于垂直居中却没用,下例为证:
原因何在?我们查一下 CSS 2 的标准:计算高度时如果
margin-top
或 margin-bottom
的值为 auto
,则它们的 ‘used value’ 为
0
。也就是在计算高度时,margin 根本就没有 auto
的概念。
好吧,那让我们静下来想想,既然 auto
不能用,那我们自己设置不就行了吗?当然这就需要事先知道需要居中的元素的高度,再用 calc
指定 margin-top
就能搞定了。
诶?怎么跟说好的不一样?说好的这回就能居中呢?上网一查,CSS 果然是坑啊。
W3school 就写得明明白白:如果使用百分比作为 margin-top
的值,则百分比的基准是父元素的 宽度 。好吧,三观都粉碎了。但再仔细一查,margin-top
是按父元素的宽度算,但
top/bottom
是按父元素的高度算啊!于是我们想到了用 position: relative
+
top: calc(50% - height/2)
的手段:
皇天不负苦心人,终于被我们给拿下了!这时身后的设计表示:你再帮我在居中的元素里加点东西吧。WTF?居中元素的高度不准变啊,混蛋!
于是我们下面要处理的就是未知父元素高度,未知子元素高度情况下的垂直居中问题(图来源为 CSS-trick):

vertical-align + table
尽管垂直居中问题困扰着我们,更让人困扰的是 CSS 里居然有一个属性名为
vertical-align,而且它有个值是 vertical-align: middle
!但是用它根本不能垂直居中啊!谁设计的,老实站出来 -_-
好吧,既然不明白为什么,那就继续好好看文档吧:vertical-align
是用来指定内嵌元素(inline element) 和 table-cell 的垂直对齐方式。我们先将 元素转换成 table
来试试对齐。首先为父元素加上 display: table
,为子元素加上 display: table-cell
来将它们变成表格的样式,再为子元素加上 vertical-align: middle
即可。如下例所示。
嗯,居中是居中了,而且也跟子元素的实际高度无关,但怎么感觉有点奇怪?嗯,是的,奇怪是因为父元素的宽度变小了,不像原来是 100% 的宽度。原因是 table
本质上也是 inline 元素,因此现在变成 inline 的父元素,它的宽度将与子元素的宽度相同。当然,我们也可以为父元素加上 width: 100%
来强制指定它的宽度。
另一个问题是子元素的高度变得和父元素一样高了。这对读者而言也许是问题,也许不是,就要自己考虑了。
伪元素的救赎
前面说到 vertical-align
可以用于垂直对齐,但它只能用于 inline 元素。比起
table
,更为直接 的想法就是把子元素改成 display: inline-block
,并加上
vertical-align: middle
。只是可惜的是这样并不成功。
原因是 vertical-align
指的是当前 inline 元素自己,与其它 inline 元素如何对齐。而我们现在的情况是,只有一个 inline 元素,那自己跟自己,怎么对齐嘛。
但如果你用过 :before
或 :after
伪元素的话,这就不是一个问题了。我们可以添加伪元素,让它的高度与父元素相同,这样子元素垂直对齐时就能居中了。如下图(来源为CSS-trick)

这里要注意的是,为一个元素添加为元素,相当于为当前元素添加了子元素,因此为了生成一个 100% 高度的伪元素,我们需要对父元素添加伪元素。如下例:
嗯,看起来好像很不错了吧!只是不是特别喜欢这种方法,因为如果我们需要使用父元素的伪元素做一些其它的事情,同时又需要居中,那我们就无能为力了。不过 CSS 是在不断发展的,在 CSS3 中,我们又多了一些选择。下面我们介绍两种。
transform 的神力
之前我们想到了用 position: relative
+ top: calc(50% - height/2)
的方法,但这种方法需要知道子元素的高度,但有了
transform,我们就可以用 translateY(-50%)
来达到 - height/2
的目的,而不需要知道居中元素的高度。
只需要简单的三步:
.center-container {
position: relative;
top: 50%;
transform: translateY(-50%);
}
富人的思虑
现在已经有了许多的方法来实现垂直居中,尽管方法的效果不一,难度各异,可总的来说还是够用了。但一旦拥有的选择多了,反而无从下手了。那么不必着急,让我们看看它们的最后一个痛点:
<div class="container">
<div class="vertical">
<p id="p1"> A paragraph 1 </p>
<p id="p2"> A paragraph 2 </p>
</div>
</div>
如上 HTML 文件,我们为了居中 p1
和 p2
,而为它们加了一个层包裹层
.vertical
。虽然也不是什么难事,但在某些情形下,我们是不能修改文档的结构的,其中一种可能是文档的内容是动态生成的。也就是,我们希望在现有的文档结构下,让某些内容垂直居中,这也许是最后一个痛点了。
那么下面我们就来看看最终的杀器:flexbox。
终结者 flexbox
flexbox 是 CSS3 为我们带来的瑞士军刀,几乎一切布局相关的问题都能用 flexbox 解决。这里我们先用实例来解决垂直居中的问题。如下:
可以看到,也是简单的3行:
.container {
display: flex;
flex-direction: column;
justify-content: center;
}
需要注意的是 CSS3 的支持问题。例如 IE 需要 IE11 才能支持。
关于 flexbox 如何使用,可以参考 A Complete Guide to Flexbox。
可以说,整篇文章就是一句 margin: 0 auto
所引发的血案。而通过一步步地深入,我们也一步步接近关于 CSS 的丑陋真相。以及旧社会(CSS2)下的人们水深火热的生活,但好在社会是在不断发展进步的。我们最终还是迎来的美好的新时代。
由于本人水平有限,难免会有错误,还请不吝赐教。
Recommend
-
78
划重点,这是一道面试必考题,很多面试官都喜欢问这个问题,我就被问过好几次了 要实现上图的效果看似很简单,实则暗藏玄机,本文总结了一下CSS实现水平垂直居中的方式大概有下面这些,本文将逐一介绍一下,我将本文整理成了一个github仓库,欢迎大家star 仅居中
-
54
我们在编辑一个版面,通常都会用到水平居中和垂直居中来设计,而水平居中很好处理,不外乎就是设定margin:0 auto;或是text-align:center;,就可以轻松解决掉水平居中的问题,但一直以来最麻烦对齐问题,都是“垂直居中”这个讨人厌的设定,以下将
-
18
梳理下平时常用css水平垂直居中方式~ 使用flex布局 HTML <div class="box"> <div class="child"></div> </div> CSS .box { width: 100vw; height: 500px;...
-
47
前言 本文总结一些水平和垂直居中的方案。 水平居中 行内元素 行内元素的...
-
12
图片和文字垂直居中对齐漂洋过海来看你IT俱乐部-码出人生图片和文字垂直居中对齐Dec 18, 2020CSS4...
-
10
我们都知道,固定高宽的div在网页中垂直居中很简单,相信大家也很容易的写出来,但是不是固定高宽的div如何垂直居中呢?我们在网页布局,特别是手机等web端网页经常是不固定高宽的div,那么这些div如何垂直居中呢?这篇文章,我总结一下。 固定高宽div...
-
11
怎么让一个div 垂直水平居中代码片段// HTML <div class="parent"> <div class="child"></div> </div>.parent{ position:relative; } // 第一种 .child{ pos...
-
10
CSS 实现垂直居中 2016-06-29 Wednesday 我们有这样一个结构的 HTML: <div class="parent"> <div class="children"></div></div>
-
6
一、问题描述: 当高度固定或不固定时,单行或多行文本难以实现垂直居中; 二、解决方法: 1、使用line-height属性,将line-height设置与元素高度等高。 局限性:只适用于单行文本,局限性大。 .box {...
-
23
CSS之垂直水平居中的背后 最开始,我想说,这个体系...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK