1999 字
10 分钟
垂直居中的几种方式

在阅读此文章之前要搞明白行内元素和块级元素的区别,和其常用的标签

行内元素和块级元素

行内元素垂直居中#

1. 设置外层块元素的heightline-height为相同的值#

适用范围:作用于单行为文字,使文字垂直居中显示

原理:line-heightfont-size的计算之差(在css中成为“行间距”)分为两半,分别加到一个文本行内容的顶部和底部。(可以包含这些内容的最小框就是行框)实现了单行文字居中,代码如下:

<body>
<style>
.container {
height: 50px;
line-height: 50px;
background:aqua;
}
.content {
background-color: bisque;
}
</style>
<div class="container">
<span class="content">垂直居中</span>
</div>
</body>

2. vertical-align#

适用范围:外层块元素包含大于一个行内元素需要垂直居中时 (如图片和文字需要垂直居中显示时),可以通过对图片的标签或文字的标签(行内元素)设置vertical-align,可以达到效果;

特点:

  • 父级块元素不需要设置宽高
  • 只需将基线较高的行内元素设置vertial-align就行

vertical-align属性的定义:该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。允许指定负长度值和百分比值。这会使元素降低而不是升高。在表单元格中,这个属性会设置单元格框中的单元格内容的对齐方式。

<body>
<style>
.container {
background: aqua;
}
.content {
background-color: bisque;
}
img {
vertical-align: middle;
}
</style>
<div class="container">
<span class="content">垂直居中</span>
*[Image missing: bd_logo1.png]*
</div>
</body>

3. 外层父元素display: table-cell;vertical-align: middle#

特点:

  • 外层元素需要设置高度

适用范围: 适用于在块元素内存在单个行内块元素,将它垂直居中;

<body>
<style>
.container {
background: aqua;
height: 300px;
display: table-cell;
vertical-align: middle;
}
</style>
<div class="container">
*[Image missing: bd_logo1.png]*
</div>
</body>

[Image missing: image-20200326110227357.png]

4. display:flex; align-items:center#

特点:

  • flex布局
  • 父元素可以不设置高度,宽度由内部行内元素撑起(这里设置高度是为了看的更清楚)
<body>
<style>
.container {
height: 300px;
background: aqua;
display: flex;
align-items: center;
}
img {
max-width: 300px;
}
</style>
<div class="container">
<span>12111111111111111111111111111111111111111111111111eeeeeeeeeeee1111111dwaedwqqqqqqqqqqqqqqqqq</span>
*[Image missing: bd_logo1.png]*
</div>
</body>

5. 绝对定位+负外边距;#

适用范围:包裹的行内元素必须是可以设置高度的,但是像文本元素是不建议使用这个的,因为文本的内容不确定,除非定高且设置超出溢出

<body>
<style>
.container {
height: 300px;
background: aqua;
position: relative;
}
img {
height: 200px;
margin-top: -100px;
top: 50%;
position: absolute;
}
</style>
<div class="container">
*[Image missing: bd_logo1.png]*
</div>
</body>

块级元素垂直居中#

类似,不解释

多行文本垂直居中#

利用 display:table;display:table-cell; 来实现多行文本的垂直居中

<body>
<style>
.container {
height: 300px;
background: aqua;
display: table;
}
p {
display: table-cell;
vertical-align: middle;
background-color: bisque;
}
</style>
<div class="container">
<p>
dsadwqdssacadseqdsfcdsfsasddsa
dwqdssacadseqdsfcdsfsasddsadwqd
ssacadseqdsfcdsfsasddsadwqdssaca
dseqdsfcdsfsasddsadwqdssacadseqds
fcdsfsasddsadwqdssacadseqdsfcdsfsasd
</p>
</div>
</body>

未知元素的宽高情况#

在前面的实现行内元素的垂直居中中有提到几种方法

1. 组合使用display:table-cellvertical-aligntext-align#

使父元素内的所有行内元素水平垂直居中(内部div设置display:inline-block即可)这在子元素不确定宽度和高度时

与其他一些display属性类似,table-cell同样会被其他一些css属性破坏,例如float,position:absolute,所以在使用display:table-cell时,尽量不要使用float或者position(可以考虑为之增加一个父div定义float等属性。);设置了table-cell的元素对宽度和高度敏感(在父元素上设置table-row等属性,也会使其不感知height。),对margin值无反应,响应padding属性

<body>
<style>
.father {
width: 400px;
height: 200px;
border: 1px solid #000;
display: table-cell;
text-align: center;
vertical-align: middle;
}
.son {
width: 200px;
height: 100px;
background: red;
display: inline-block;
}
</style>
<div class="father">
<div class="son">
display:table-cell;</br>text-align:center;</br> vertical-align:middle
</div>
</div>
</body>

对table-cell元素设置百分比(如100%)的宽高值是无效的,但是可以将元素设置display

,再将父元素设置百分比跨高,子元素table-cell会自动撑满父元素。这就可以做相对于整个页面的水平垂直居中。嗯,看下面的代码

<body>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#box {
display: table;
width: 100%;
height: 100%;
}
.father {
width: 400px;
height: 200px;
border: 1px solid #000;
display: table-cell;
text-align: center;
vertical-align: middle;
}
.son {
width: 200px;
height: 100px;
background: red;
display: inline-block;
}
</style>
<div id="box">
<div class="father">
<div class="son">
display:table-cell;</br>text-align:center;</br> vertical-align:middle
</div>
</div>
</div>
</body>

2. display的方法#

参考上面所说的行内元素的方法

  1. 设置container的display的类型为flex,激活为flexbox模式。

  2. justify-content定义水平方向的元素位置

  3. align-items定义垂直方向的元素位置

3. display +伪元素生成content内容#

实现原理:原理:利用inline-blockvertical-align: middle去对齐before伪元素,before伪元素的高度与父对象一样,就实现了高度方向的对齐。居中块的尺寸可以做包裹性、自适应内容,兼容性也相当好。缺点是水平居中需要考虑inline-block间隔中的留白(代码换行符遗留问题。)。(宽度是已知的,高度可以是未知的)

(这里子元素加了宽高是为了方便看,去掉也无所谓)

<body>
<style>
.father {
width: 400px;
height: 200px;
border: 1px solid #000;
text-align: center;
}
.father:before {
content: " ";
display: inline-block;
vertical-align: middle;
height: 100%;
}
.son {
width: 200px;
height: 100px;
background: red;
display: inline-block;
vertical-align: middle;
}
</style>
<div class="father">
<div class="son">
display:inline-block;</br>伪元素生成content内容</br>
</div>
</div>
</body>

4. 绝对定位+transform反向偏移。#

position; transform(-50%,-50%);

原理很简单:由于top、left偏移了父对象的50%宽度高度,所以需要利用transform反向偏移居中块的50%宽高

transform的计算基准是元素本身,所以这里可以用50%来做反向偏移

(这里子元素加了宽高是为了方便看,去掉也无所谓)

<body>
<style>
.father {
width: 400px;
height: 200px;
border: 1px solid #000;
position: relative;
}
.son {
width: 200px;
height: 100px;
background: red;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
<div class="father">
<div class="son">
position:absolute;</br>left:50%;top:50%;</br>transform
</div>
</div>
</body>

知道元素宽高的情况下#

1.绝对定位相对定位( 绝对定位+margin:auto;position; left:0; top:0; right:0; bottom:0; margin#

一个条件都不能少

<body>
<style>
.father {
width: 400px;
height: 200px;
position: relative;
border: 1px solid #000;
}
.son {
width: 200px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
}
</style>
<div class="father">
<div class="son">
position:absolute;</br> left:0; top:0;</br> right:0; bottom:0; </br>margin:auto
</div>
</div>
</body>

原理:

当一个绝对定位元素,其对立定位方向属性同时有具体定位数值的时候,流体特性就发生了。

具有流体特性绝对定位元素的margin的填充规则和普通流体元素一模一样:

如果一侧定值,一侧auto,auto为剩余空间大小; 如果两侧均是auto, 则平分剩余空间; 例如,下面的CSS代码:

.father {
width: 300px; height:150px;
position: relative;
}
.son {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}

如图所示流体元素会布满整个父元素,此时.son这个元素的尺寸表现为“格式化宽度和格式化高度”,和的“正常流宽度”一样,同属于外部尺寸,也就是尺寸自动填充父级元素的可用尺寸的

[Image missing: image-20200326150745436.png]

然后,此时我们给.son设置尺寸,例如

.son {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
width: 200px; height: 100px;
}

此时宽高被限制,原本应该填充的空间就被多余了出来,这多余的空间就是margin:auto计算的空间,因此,如果这时候,我们再设置一个margin:auto,那么:

.son {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
width: 200px; height: 100px;
margin: auto;
}

我们这个.son元素就水平和垂直方向同时居中了

2. 绝对定位+margin反向偏移#

在上面的行内块元素种有提及到

position:absolute;
top:50%;
left:50%;
margin-left:-(width+padding)/2+'px';
margin-top:-(height+padding)/2+'px';

margin值的设置不能使用百分比,因为margin是基于父元素的宽度来计算百分比的

这个原理和上面的方案4很相似,由于top、left偏移了父对象的50%宽度高度,所以需要利用margin反向偏移居中块的50%宽高

垂直居中的几种方式
https://nollieleo.github.io/posts/垂直居中的几种方式/
作者
翁先森
发布于
2020-03-26
许可协议
CC BY-NC-SA 4.0