# CSS 居中专项讲解

对于 CSS 新手来说,居中效果绝对是能排上前几的新手常见难题。

对于不同类型的元素的性质认识不够深刻,又常常在搜索解决方法时没能准确描述自己想要居中的元素的类型,导致出现诸如文本对齐的方法用在块元素上的错误。

关于居中的属性实在不算少,故分清不同情况来设置不同的属性是非常重要的一步。

# 内容预览

按情景分类:

按方法分类:

  • 水平居中
    • text-align
    • auto-margin
    • [flex] justify-content
  • 垂直居中
    • padding
    • line-height
    • absolute & -margin | transform
    • [flex] & auto-margin
    • [flex] align-item
    • [flex] flex-direction & justify-content
    • [flex] align-content (wrap)
    • [table-cell] vertical-align: middle
  • 水平垂直居中
    • [grid] auto margin

关于显示问题😥

一些对于在 markdown 内嵌 HTML 支持较差的编辑器(如 github)会影响本文示例的正常显示,建议点击此处 (opens new window)阅读本文。

⚠ 文中所列出的 CSS 样式并非效果的所有样式,如发现实现的效果有出入可以直接右键查看本页面对应示例的源码(示例的样式全部内嵌于HTML标签中)。

# 水平居中

# 内联元素

文本、inline-block、inline-table 等等都可以使用text-align: center的方法居中。

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

效果:

centered text


# 块元素

通过 margin 设置左右外边距为auto,浏览器会自动均分左右剩余的空间给元素的左右外边距,从而很好的解决有固定width的块元素的居中问题。

.center-block {
    margin: 0 auto;
}

效果:


# 多个内联块元素

将他们用<div>包裹起来,然后设置如下对齐方式(二选一):

/* 内联块方法 */
.inline-block-center {
    text-align: center;
}

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

/* Flex盒子方法 */
.flex-center {
    display: flex;
    justify-content: center;
}

效果:

inline block

flexbox(默认自动拉伸)


# 垂直居中

# 内联元素

  • 如果父元素没有设置固定宽高,则父元素设置相同上下padding即可;
  • 稍微“trick”一点的,可以设置父元素的行高属性line-heightheight相同(如果父元素没有height的话就不用设置了)。
/* padding */
.link {
    padding: 40px 0;
}

/* line-height */
.center-text-trick {
    line-height: 110px; 
    /* 设置nowarp避免尺寸问题导致换行破坏样式 */
    white-space: nowrap;
    overflow: hidden;
}

效果:

用padding来撑起垂直居中

用line-height的方法垂直居中

line-height 方法存在的小问题就是用鼠标去划取选中文字时能够看到不太正常的行高,但有的时候(比如一个<a>链接按钮)能够提供更大的选中范围,利于操作。


# 块元素

如果不想使用 flexbox 的方法,可以用定位+移位的方法实现垂直居中:

/* 
 * 父元素需要设置为relative是因为子元素的absolute定位
 * 是相对于最亲的非static定位的父元素来进行定位的
 */
.parent {
    position: relative;
}

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

效果:


如果你知道子元素的高度,可以直接使用设置负值margin的方法。(可能会牺牲普适性提高一点点渲染速度吧)

child {
    height: 100px;
    padding: 20px;
    position: absolute;
    top: 50%;
    margin: -70px 0 0;
}

效果就不演示了🐟


配合 flex 布局设置margin: auto实现(垂直)居中也是一种非常简单有效的方法。

.parent {
    display: flex;
}

.margin-center {
    margin: auto 0;
}

效果:


当然,下面 多个元素 小节介绍的方法大多也可以应用于单个块元素上。

还有一种利用 CSS table-cell 的 trick,可以使用vertical-align: center垂直居中。介于不太符合一般情况下的语义环境故不介绍了。


# 多个元素

对于多个内联元素来说,设置相同的上下padding仍然是个不错的办法,但如果不合适或者是块元素的话,可以试试使用 flexbox。

多个(区块)元素垂直方向堆积的方法:

.flex-center-vertically {
    display: flex;
    /* 设置主轴为竖向 */
    flex-direction: column;
    /* 主轴方向居中 */
    justify-content: center;
}

效果:(每个元素被点框框起来以易于区分)

one two three Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.


多个元素时往水平堆积的方法:

.flex-center-vertically {
    display: flex;
    /* 交叉轴方向(垂直方向)居中 */
    align-item: center;
}
one two three Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

此外,对于多个内联元素,如果其拥有多个主轴线(多行),那么可以使用align-content来垂直居中:

.flex-center-vertically {
    display: flex;
    align-content: center;
    flex-wrap: wrap;
}
one two three Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

# 在行中

vertical-align属性虽然也是关于内联元素的垂直居中的属性,但vertical-align: middle;的作用效果是“该元素在它所在的那一行以垂直中间为基准对齐”。

span {
    display: inline-block;
    vertical-align: middle;
}

效果:

这是一个位于段落中的橙色方块。


由此可以引申出关于在父元素内垂直居中还有一种奇淫技巧——“ghost element”(了解即可)

.ghost-center {
    position: relative;
}

/* 创建一个看不见的、与父元素登高的垂直居中元素 */
.ghost-center::before {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: middle;
}

.ghost-center p {
    display: inline-block;
    vertical-align: middle;
    /* 需要设置 width */
}

效果:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.


# 水平垂直居中

这就可以将前面两节的内容配合起来使用了,根据不同的情况、语境还有个人习惯选择不同的方法。

例如对于这个例子:

.parent {
    position: relative;
}

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

可以...

/* 负margin方法 */
.child {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -70px 0 0 -170px;
}

/* transform方法 */
.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

/* flexbox方法 */
.parent {
    display: flex;
    justify-content: center;
    align-items: center;
}

/* flex + margin方法(仅对于单元素) */
.parent {
    display: flex;
}
.child {
    margin: auto;
}

还有一种非常好用的布局方法 —— Grid 布局,在“二维布局”的情况下要比“一维”的 Flex 布局要更加好用:

.parent {
    display: grid;
}

.child {
    margin: auto;
}

样例:

<style>
.parent {
    display: grid;
    height: 200px;
    width: 300px;
    background: #21252b;
}

.child {
    margin: auto;
}

.marked {
    border: 1px dotted #ccc;
    background: #282c34;
}
</style>

<div class="parent">
    <div class="child">
        <span class="marked">I'm centered!</span>
        <span class="marked">I'm centered!</span>
        <p class="marked">I'm centered!</p>
  </div>
</div>

效果:

I'm centered! I'm centered!

I'm centered block!


# 总结

由此可见,居中这件事儿交给 CSS 来做是没有什么大问题的。最后再过一下本文介绍的居中方法:

  • 水平居中
    • text-align
    • auto-margin
    • [flex] justify-content
  • 垂直居中
    • padding
    • line-height
    • absolute & -margin | transform
    • [flex] & auto-margin
    • [flex] align-item
    • [flex] flex-direction & justify-content
    • [flex] align-content (wrap)
    • [table-cell] vertical-align: middle
  • 水平垂直居中
    • [grid] auto margin

# 本文参考


上次更新: 2020/3/1 20:30:40