Skip to content

Centering in CSS: A Complete Guide(css居中方案完全指南) #8

@qppq54s

Description

@qppq54s

翻译自centering-css-complete-guide

居中是人们对css抱怨的最多的问题之一。它为什么这么难?要吃人。我认为问题并不在居中很难,而是在于在各种情况下要采取不同的方案去实现,合适的使用才是关键。

所以,让我们画一个决定树去尝试让居中变得容易一点。

我需要在这种情况下实现居中...

水平居中

是否为行内元素(inline 或者 inline-*)?

在块级父元素中对行内元素居中,可以使用下面的方法

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

这种方法对于inline,inline-block,inline-table,inline-flex等等都适用。

是否为块级元素(inline 或者 inline-*)?

要让块级元素居中,可以设置margin-left和margin-right为auto(而且必须设置width,不然这个元素就是全宽的,不需要居中)。看下面的代码:

.center-me {
  width: 10px;
  margin: 0 auto;
}

这样无论在什么宽度的宽级元素或者父元素中都可以实现居中。
注意:你不能使用float让元素居中。但是有一个特殊方法

是否有多个块级元素?

如果存在多个块级元素在同一行居中,更好的选择可能是使用另外一种display类型。下面是将块级元素设置为inline-block和使用flexbox居中的案例:

.inline-block-center {
  text-align: center;
}
.inline-block-center div {
  display: inline-block;
  text-align: left;
}

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

垂直居中

垂直居中在css中有点棘手。

是否为行内元素

是否为单行的行内元素

有些情况下行内元素/文字能够垂直居中是因为它们的上面和下面填充了一样的padding

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

如果在某些情况下不能使用padding,那么对于不换行的元素,有个技巧就是设定line-height和height一样,内容就会居中。

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

是否为多行的行内元素

给元素的顶部和底部赋予相同的padding也能让多行文字居中,但是如果这样行不通的话,可能是文字所在的元素是table内,或者css设置的display:table内。在这种情况下,就要用到vertical-align属性了,这种方法和通常的垂直居中方式不太一样。

<table>
  <tr>
    <td>
      I'm vertically centered multiple lines of text in a real table cell.
    </td>
  </tr>
</table>

<div class="center-table">
  <p>I'm vertically centered multiple lines of text in a CSS-created table layout.</p>
</div>


table {
  background: white;
  width: 240px;
  border-collapse: separate;
  margin: 20px;
  height: 250px;
}

table td {
  background: black;
  color: white;
  padding: 20px;
  border: 10px solid white;
  /* default is vertical-align: middle; */
}

.center-table {
  display: table;
  height: 250px;
  background: white;
  width: 240px;
  margin: 20px;
}
.center-table p {
  display: table-cell;
  margin: 0;
  background: black;
  color: white;
  padding: 20px;
  border: 10px solid white;
  vertical-align: middle;
}

如果用不了table这样子的方式,或许可以试试用flexbox?flex内部的子元素可以轻松的居中。

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

注意这种情况只在父元素有指定的高度时才会生效。

如果上面的所有方法都不行,你还可以尝试“伪类”的黑科技,将一个全高的伪类元素放在容器中并且垂直居中。 具体实现原理是怎么样的?

.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;
}

是否为块级元素

元素的高度是否确定

在web页面布局中,不知道元素的高度的情况是很常见的,有很多原因:如果宽度发生改变,文本流可能会改变高度。文本样式的变化也会改变高度。文本数量的变化也可以改变高度。具有固定宽高比的元素,比如图像,在调整大小时会改变高度。等等情况。

但是如果你可以确定高度,你可以用如下方式实现垂直居中:

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  height: 100px;
  margin-top: -50px; /* 需要计算padding和border如果不是box-sizing: boder-box */
}

不知道元素的高度

仍然可以把元素放到50%高度然后上升自身的50%以居中:

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

能不能使用flexbox

没啥大惊小怪,在flexbox里面很容易就可以实现。

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

水平垂直居中

你可以以任意方式结合上面的技巧来实现完美居中的元素。但是我发现大致可以分为以下几种情况:

元素的宽高是否确定

在绝对定位和设置50%/50%后设置宽高的一半的负margin可以获得兼容性极好的居中:

.parent {
  position: relative;
}

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

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

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

元素的宽高无法确定

如果不确定元素的宽高,可以使用transform属性和50%的负translate来设置居中:

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

flexbox

flexbox里要实现居中,只用同时使用两个居中属性

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

grid

这是一个小技巧对于单个元素比较有效:

body, html {
  height: 100%;
  display: grid;
}
span { /* 居中的元素 */
  margin: auto;
}

结论

你现在可以在任何情况下实现元素居中了。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions