4

原文出处:Centering in CSS: A Complete Guide

本文只给出了不同条件下的实现方式,未对原理做探讨。
PS:原来要显示 jsfiddle 和 CodePen 之类网站的代码预览,只需将其以 Markdown 语法来插入链接即可。


水平居中

行内元素

对于行内元素(inline)或复合行内元素(inline-*),直接为其父元素设置文本居中即可。

.center-children {
  text-align: center;
}

http://codepen.io/chriscoyier/pen/HulzB

该方法适用于 inlineinline-blockinline-tableinline-flex 之类的元素。

块级元素

对于块级元素,如果给定了宽度,直接设置左右边距为 auto 即可。
注意:对于未指定宽度的元素,默认会占满允许的最大宽度,这时设置居中是无效的。

.center-me {
  margin: 0 auto;
}

http://codepen.io/chriscoyier/pen/eszon

不管元素或者父元素的宽度如何,只要指定了宽度,该方法就有效。

但是,对于设置了浮动(float)的元素就不行了,这里有一个取巧的办法可以实现浮动元素居中。

多个块级元素

对于多个块级元素需要整体居中的情况,还可细分为以下三类:

并排显示,高度无要求

如果不要求并排的多个块级元素有同样的高度,那么可为这些块级元素的父元素设置 display: inline-block 属性,以实现所需效果。

<main class="inline-block-center">
  <div>I'm an element that is block-like with my siblings and we're centered in a row.</div>
  <div>I'm an element that is block-like with my siblings and we're centered in a row. I have more content in me than my siblings do.</div>
  <div>I'm an element that is block-like with my siblings and we're centered in a row.</div>
</main>
.inline-block-center {
  text-align: center;
}
.inline-block-center div {
  display: inline-block;
  text-align: left;
}

http://codepen.io/chriscoyier/pen/ebing

并排显示,要求相同高度

如果要求多个块级元素并排居中且高度相同,则要为其父元素设置 display: flex 属性。

<main class="flex-center">
  <div>I'm an element that is block-like with my siblings and we're centered in a row.</div>
  <div>I'm an element that is block-like with my siblings and we're centered in a row. I have more content in me than my siblings do.</div>
  <div>I'm an element that is block-like with my siblings and we're centered in a row.</div>
</main>
.flex-center {
  display: flex;
  justify-content: center;
}

成一列显示

如果只是需要让多个块级元素整体水平居中,并且按默认的方式纵向排列,那直接设置左右边距为 auto 即可。

http://codepen.io/chriscoyier/pen/haCGt


垂直居中

要实现元素的垂直居中就需要一些小技巧了。

行内元素

单行内容

为行内元素/文本元素设置相等的上下内边距即可实现单行元素的垂直居中。

.link {
  padding-top: 30px;
  padding-bottom: 30px;
}

http://codepen.io/chriscoyier/pen/ldcwq

如果出于种种原因不能用上面的设置上下内边距的方式,那么可以设置行高与元素的高度相同,这样也能实现垂直居中的效果,但是使用这种方法要保证文本不会换行。

.center-text-trick {
  height: 100px;
  line-height: 100px;
  white-space: nowrap;
}

http://codepen.io/chriscoyier/pen/LxHmK

多行内容

对多行文本设置相等的上下内边距也是可以实现垂直居中的,但是有时候会因为文本在表格的单元格中,或者文本所属的元素通过 CSS 设置为表格单元格的表现方式,而无法实现垂直居中的效果。在这种情况下,可以用 vertical-align 属性来实现垂直居中。

http://codepen.io/chriscoyier/pen/ekoFx

上面的方式不可行的话,还可以使用 flexbox,flex 只有一个子元素的话,要实现垂直居中还是很简单的。

.flex-center-vertically {
  display: flex;
  justify-content: center;
  flex-direction: column;
  height: 400px;
}

http://codepen.io/chriscoyier/pen/uHygv

对于 flexbox 方法,原文中说到父元素有指定高度之后,这种方法才有意义,但是通过测试代码发现,父元素未指定高度也是可以垂直居中的。
Remember that it's only really relevant if the parent container has a fixed height (px, %, etc), which is why the container here has a height.

除此之外,还可以使用 ghost element,这种方法是将一个完整高度的伪类放在容器中,让文本与这个伪类纵向居中对齐。

.ghost-center {
  position: relative;
}
.ghost-center::before {
  content: " ";
  display: inline-block;
  height: 100%;
  width: 1%;
  vertical-align: middle;
}
.ghost-center p {
  display: inline-block;
  vertical-align: middle;
}

http://codepen.io/chriscoyier/pen/ofwgD

块级元素

元素高度已知

在网页布局中,元素高度不确定的情况很普遍:比如元素宽度改变,文本重排之后元素高度就会改变。文本的样式不同,元素高度也会不同。文本的字数不同,元素高度也会不同。具有固定高宽比的元素,比如图片,当尺寸改变时,其高度也会变化,等等情况。

但是如果元素高度已知,可以用下面的方法来实现垂直居中:

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  height: 100px;
  margin-top: -50px; /* account for padding and border if not using box-sizing: border-box; */
}

http://codepen.io/chriscoyier/pen/HiydJ

元素高度未知

该方法就是先将元素相对于其原始位置向下移动父元素高度的一半距离,再将该元素相对其本身的高度向上移动一半,这样就能实现垂直居中的效果了。

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

http://codepen.io/chriscoyier/pen/lpema

简单粗暴的 flexbox

flexbox 的话,实现起来就简单多了。

.parent {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

http://codepen.io/chriscoyier/pen/FqDyi


水平和垂直均居中

简单地把上面提到的实现水平居中和垂直居中的方法结合起来自然是可以的,但是这个需求也可以分为以下三类来实现:

元素宽度及高度已知

将元素相对于其父元素的宽度/高度值向右并向下移动一半的距离,这时元素左上角的顶点刚好位于父元素的中心。然后再通过设置负边距值的方法,将元素相对于其自身的宽度/高度值向左并向上移动一半的距离,就可实现水平垂直均居中的效果了。并且这种方法的浏览器兼容性是很好的。

.parent {
  position: relative;
}

.child {
  width: 300px;
  height: 100px;
  padding: 20px;

  position: absolute;
  top: 50%;
  left: 50%;

  margin: -70px 0 0 -170px;
}

http://codepen.io/chriscoyier/pen/JGofm

元素的宽度或高度未知

如果元素的宽度或者高度未知,则在将元素相对于父元素的宽高往向右并向下移动一半距离后,再用 transform 属性来将其向左并向上移动自身宽度及高度值一般的距离即可。

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

http://codepen.io/chriscoyier/pen/lgFiq

flexbox 大法

要通过 flexbox 来实现水平垂直均居中,就要使用两个居中属性来实现:

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

http://codepen.io/chriscoyier/pen/msItD

PS: 刚发现还可以通过下面的方式实现子元素水平及垂直均居中:

.parent {
    display: flex;
    justify-content: center;
}

.child {
    // 不加这一条的话,子元素的高度将撑满父元素。加了这一条,才能让子元素以正常的高度显示,并且在垂直方向上居中。
    margin: auto 0;
}

总结

信 CSS,得永生


samsara0511
932 声望729 粉丝