CSS 子元素在父元素中水平垂直居中

4,701 阅读11分钟

前提: 设置子元素在父元素中水平垂直居中,一般不做特殊说明父元素都不会是行内元素。实际开发中,不要试图使用行内元素包裹一个块元素(包括行内块元素),会有莫名其妙的现象,行内元素只应嵌套行内元素或文本(文本也相当于行内元素)。

元素水平居中

image.png

场景一:子元素是块元素

方法1:父元素是块元素,左右 margin auto

如果子元素是块元素(display: block)且未设置浮动,父元素是块元素,那么可以通过设置子元素 margin-left: auto; margin-right: auto; 的方式让子元素在父元素中水平居中。

.wrapper {
  display: block;
  background-color: red;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 子元素水平居中 */
  margin-left: auto;
  margin-right: auto;
}

方法2:父元素是表格单元格,左右 margin auto

当子元素是块元素,父元素为表格单元格时,也可以使用 左右 margin auto 的方法来使子元素水平居中(同方法一)。

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成表格 */
  display: table-cell;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  margin-left: auto;
  margin-right: auto;
}

方法3:设置父元素相对定位,子元素绝对定位

方法3.1:left + translateX

当父元素相对定位,子元素设置了绝对定位时,left: 50%; transform: translateX(-50%); 实现子元素水平居中。

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用 50% 水平居中*/
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

方法3.2:负 margin

或者使用 负 margin 方法,实现子元素水平居中。此方法需要计算负 margin 的数值,因此更加推荐第一种方法。

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用负 margin 水平居中*/
  position: absolute;
  left: 50%;
  margin-left: -50px;
}

方法3.3:左右 margin:auto + left0 right0

还可以使用 左右 margin:auto 搭配 left:0; right:0; 实现绝对定位子元素的水平居中。

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用 margin: auto 实现水平居中*/
  position: absolute;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
}

场景二:子元素不是块元素

方法1:父元素是块元素,text-align: center

如果子元素是行内块元素(display: inline-block)或行内元素(display: inline;)且未设置浮动,父元素是块元素,只需给父元素设置 text-align: center; 即可让子元素在父元素中水平居中。

.wrapper {
  display: block;
  background-color: red;
  
  /* 行内块级子元素水平居中 */
  text-align: center; 
}

.son {
  display: inline-block; 
  width: 100px;
  height: 100px;
  background-color: green;
}

特别地,子元素为行内元素时,只有在被内容撑开时,父元素设置 text-align: center; 才能看到效果。另外,上面一直说的父元素是块元素的情况,其实如果父元素是行内块元素,其实对应的水平居中方法依然有效,只是需要注意由于行内块元素的特点即 可以设置宽度,如果没有设置那么宽度默认是内部 inline 元素之和 。所以只有在给行内块的父元素 设置宽度 时,以上方法才能生效!

.wrapper {
  display: inline-block;
  background-color: red;
  
  /* 父元素是行内块时,必须设置高度 */
  width: 200px;
  text-align: center;
}

.son {
  display: inline-block;
  background-color: green;
  width: 100px;
  height: 100px;
}

方法2:父元素为表格单元格,text-align:center

如果父元素为表格单元格,子元素为行内元素(包括行内块元素),那么需要设置父元素 text-align:center 来实现子元素的水平居中(同方法1)。

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成表格 */
  display: table-cell;
  
  /* 子元素是 inline-block/inline 情况 */
  text-align:center;
}

.son {
  display: inline-block;
  background-color: green;
  width: 100px;
  height: 100px;
}

场景三:子元素浮动

如果一个子元素设置了浮动,这时候我们知道如果父元素没有设置高度的话,高度将变成 0,即高度坍塌,并且子元素的宽度由内容撑开即其本身相当于一个行内块元素(可以设置宽高)。如果在父元素和子元素都设置了宽高的情况下,需要让子元素在父元素中水平垂直居中,那么我们可以让 子元素变成相对定位,再设置水平居中,方法同场景一方法3,代码如下:

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 子元素设置相对定位,再设置水平居中即可 */
  float:left;
  position:relative;
  left: 50%;
  transform: translateX(-50%);
}

万金油法:父元素设为弹性盒,justify-content: center

如果父元素是弹性盒(display: flex),那么只需要设置 justify-content: center;,其内部所有子元素将会作为一个整体水平居中。另外,你会神奇的发现如果你让父元素变成弹性盒,无论如何子元素都会变成行内块元素,哪怕强制让它变成行内元素。

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成弹性盒 */
  display: flex;
  
  /* 所有子元素作为整体水平居中 */
  justify-content: center;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
}

元素垂直居中

image.png

场景一:子元素是块元素

方法1:父元素是表格单元格,父(vertical-align: middle) + 子(上下 margin auto)

我们知道块元素设置左右 margin auto 可以实现水平居中,但是设置上下 margin auto 却实现不了垂直居中(具体原因可参见:margin:auto为什么只能实现水平居中,不能实现垂直居中)。而当父元素是表格单元格(display: table-cell;)时,只要设置父元素 vertical-align: middle; 也可以实现子元素垂直居中!

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成表格 */
  display: table-cell;
  vertical-align: middle;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
}

方法2:父元素相对定位,子元素绝对定位

同上述子元素绝对定位时设置水平居中方式,我们依然可以使用 transform 或者 负 margin 或者 上下 margin auto 方法实现子元素在垂直方向上的居中。

方法2.1:top + translateY

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用 50% 实现垂直居中*/
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

方法2.2:负 margin

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用负 margin 垂直居中*/
  position: absolute;
  top: 50%;
  margin-top: -50px;
}

方法2.3:上下 margin auto + top0 bottom0

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用 margin: auto 实现垂直居中*/
  position: absolute;
  top: 0;
  bottom: 0;
  margin-top: auto;
  margin-bottom: auto;
}

场景二:子元素是行内元素(单行文本)

方法1:父元素的行高和高度保持一致

以上三种场景下,子元素是块元素或者行内块元素,方法皆有效。但如果子元素是行内元素,想要在一个块元素中垂直居中,则只需让 父元素的行高和高度保持一致 即可。

.wrapper {
  display: block;
  background-color: red;
  height: 200px;
  line-height: 200px;
}

.son {
  display: inline;
  background-color: green;
}

方法2:上下等大小的 padding

或者你也可以给父元素添加 上下等大小的 padding 来实现行内元素的垂直居中,但是这种方法就不能再设置父元素的高度了,需要让父元素由内部的行内元素高度撑开。

.wrapper {
  display: block;
  background-color: red;
  padding-top: 100px;
  padding-bottom: 100px;
}

.son {
  display: inline;
  background-color: green;
}

场景三:子元素浮动

和浮动子元素水平居中方法类似,想要一个浮动子元素在父元素中垂直居中,也需要让 子元素变成相对定位,再设置垂直居中,方法同场景一方法2,代码如下:

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 子元素设置相对定位,再设置垂直居中即可 */
  float:left;
  position:relative;
  top: 50%;
  transform: translateY(-50%);
}

万金油法:父元素设为弹性盒,align-items: center

如果父元素是弹性盒,那么只需要设置 align-items: center;,其内部所有子元素将会作为一个整体垂直居中。

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成弹性盒 */
  display: flex;
  
  /* 所有子元素作为整体垂直居中 */
  align-items: center;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
}

子元素水平垂直居中

image.png

综合上面的情况,我们很容易组合出下面几种让子元素水平垂直居中的方法:

方法1:父相子绝 + top 50% + left 50% + translate -50%

结合 translateX 和 translateY,我们可以得出如下水平垂直居中方法:

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
  
  position: relative;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 绝对定位使用 translate 50% 实现水平垂直居中*/
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

方法2:子相 + top 50% + left 50% + translate -50%

和方法一类似,如果子元素不是绝对定位,而是相对定位,也可以通过同样的方法设置水平垂直居中。

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 相对定位使用 translate 50% 实现水平垂直居中*/
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

方法3:父元素表格单元格 + margin auto

如果父元素是表格,我们也可以通过以下方法实现水平垂直居中:

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成表格 */
  display: table-cell;
  vertical-align: middle;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 子元素设置 margin auto 实现水平垂直居中 */
  margin: auto;
}

特别地,如果子元素是行内块或者行内元素时,父元素需要设置 text-align:center,才能实现水平垂直居中。

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成表格 */
  display: table-cell;
  vertical-align: middle;
  
  /* 兼容子元素是 inline-block/inline 情况 */
  text-align:center;
}

.son {
  display: inline-block;
  background-color: green;
  width: 100px;
  height: 100px;
}

方法4:子元素是浮动元素的居中方式

如果一个子元素设置了浮动,这时候我们知道如果父元素没有设置高度的话,高度将变成 0,即高度坍塌,并且子元素的宽度由内容撑开即其本身相当于一个行内块元素(可以设置宽高)。如果在父元素和子元素都设置了宽高的情况下,需要让子元素在父元素中水平垂直居中,那么我们可以让 子元素变成相对定位,再设置水平垂直居中,具体方法如下:

.wrapper {
  display: block;
  background-color: red;
  width: 200px;
  height: 200px;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
  
  /* 子元素设置相对定位,再设置水平垂直居中即可 */
  float:left;
  position:relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  
  /* 或者使用负 margin
  margin-top: -50px;
  margin-left:-50px; 
  */
}

方法5(万金油):flex 布局

父元素设置为弹性盒,并设置 justify-content: center; align-items: center; 即可同时实现子元素水平垂直居中。

.wrapper {
  background-color: red;
  width: 200px;
  height: 200px;
  
  /* 父元素变成弹性盒 */
  display: flex;
  
 /* 所有子元素作为整体水平垂直居中 */
  justify-content: center;
  align-items: center;
}

.son {
  display: block;
  background-color: green;
  width: 100px;
  height: 100px;
}

参考资料

  1. CSS子元素在父元素中水平垂直居中的几种方法
  2. CSS-水平居中、垂直居中、水平垂直居中
  3. 水平居中、垂直居中、水平垂直居中、浮动居中、绝对定位居中.......帮你搞定