实现垂直居中

对于水平居中,我们可以很自如的使用CSS进行居中,对于行内元素:text-align: center; 对于块级元素:margin: 0 auto; 当对元素进行垂直居中时,就显得格外的麻烦。

为此,我特地查找了各种资料整理了一些实现垂直居中的各种方法。

行内元素

行内元素本身padding-top和padding-bottom是相等的,所以说"天然地"垂直居中。

常见的行内元素有:

i , code, em, strong, a, br, img, script, span, sup, button, input, label, select, textarea

单行

方式一:默认

只需简单地设置一下padding就可以达到垂直居中。

html:

<!-- HTML -->
<main>
  <a href="#0">a元素</a>
    <span>span元素</span>
</main>

CSS样式:

body {
    background-color: #f06d06;
    font-size: 1em;
}

main {
    background: white;
  margin: 20px 0;
    padding: 80px;
}

main a, main span{
    background: black;
    color: white;
    padding: 40px;
    text-decoration: none;
}

效果:

center-inline.png

方式二:设置line-height和父元素高度一致

html:

    <main>
      <div>一些需要垂直居中的文本</div>
    </main>

CSS样式:

      body {
        background: #f06d06;
        font-size: 1em;
      }

      main {
        background: white;
        margin: 20px 0;
        padding: 40px;
      }

      main div {
        background: black;
        color: white;
        height: 80px;
        line-height: 80px;
        padding: 20px;
        width: 50%;
        white-space: nowrap;
      }

效果:

center-line-height.png

多行

方式一:

使用display: table或使用html的table表格元素设置vertical-align: middle;实现.

我们来看看MDN对vertical-align属性的描述:

vertical-align 用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式。

html:

    <table>
      <tr>
        <td>
            我在好几篇小说中都提到过一座废弃的古园,实际就是地坛。许多年前旅游业还没有开展,园子荒芜冷落得如						同一片野地,很少被人记起。
        </td>
      </tr>
    </table>
        <!-- display: table -->
    <div class="center-table">
      <p>
        地坛离我家很近。或者说我家离地坛很近。总之,只好认为这是缘分。地坛在我出生前四百多年就座落在那儿了,				而自从我的祖母年轻时带着我父亲来到北京,就一直住在离它不远的地方一五十多年间搬过几次家。
      </p>
    </div>

CSS样式:

      body {
        background: #f06d06;
        font-size: 1em;
      }

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

      table td {
        background: black;
        color: white;
        padding: 20px;
        border: 10px solid white;
        /* 默认就是 vertical-align: middle; */
      }
            /* 父元素设置为table */
      .center-table {
        display: table;
        height: 250px;
        background: white;
        width: 240px;
        margin: 20px;
      }
            /* 子元素设置为tabel-cell */
      .center-table p {
        display: table-cell;
        margin: 0;
        background: black;
        color: white;
        padding: 20px;
        border: 10px solid white;
        /* 设置vertical-align: middle垂直居中 */
        vertical-align: middle;
      }

效果:

center-table.png

方式二:

display: flexjustify-content: center

html:

    <div class="flex-center">
      <p>
        可搬来搬去总是在它周围,而且是越搬离它越近了。我常觉得这中间有着宿命的味道:仿佛这古园就是为了等我,				而历尽沧桑在那儿等待了四百多年。
      </p>
    </div>

CSS样式:

      body {
        background: #f06d06;
        font-size: 1em;
      }

      div {
        background: white;
        width: 240px;
        margin: 20px;
      }

      .flex-center {
        background: black;
        color: white;
        border: 10px solid white;
        display: flex;
        flex-direction: column;
        justify-content: center;
        height: 200px;
        resize: vertical;
        overflow: auto;
      }
      .flex-center p {
        margin: 0;
        padding: 20px;
      }

效果:

center-flexbox.png

注意: 实现该效果的盒子必须要提前固定高度,我们知道,弹性盒子的“面积”就是里面的元素撑开的,设置justify-content: center系统就可以合理地分配上下的空间以达到居中。

块级元素

块级元素垂直居中应该是应用得最广的了。

常见的块级元素有:

div, p, h1-h6, form, table, ul, ol, li, pre, hr, blockquote.

HTML5语义化标签:

header, article, aside, footer, section, main...

不使用flexbox

方式一:

已知子父元素高度情况下使用定位。

html:

    <main class="parent">
        <div class="child"></div>
    </main>

CSS样式:

        body{
            font-size: 1em;
            background-color: #f06d06;
        }
        .parent{
            background-color: white;
            height: 300px;
            width: 300px;
            position: relative;
        }
                /* 子元素height/2 + top=100px = 父元素/2 */
        .child{
            position: absolute;
            top: 100px;
            left: 20px;
            right: 20px;
            height: 100px;
            background-color: black;
        }

效果:

center-block01.png

方式二:

知道父元素高度不知道子元素高度情况下:

使用定位和transform.

html:

    <main>
      <div>一些内容撑开高度,但不知道具体高度。。</div>
    </main>

CSS样式:

      body {
        font-size: 1em;
        background-color: #f06d06;
      }

      main {
        background: white;
        height: 300px;
        margin: 20px;
        width: 300px;
        position: relative;
      }

      main div {
          position: absolute;
          top: 50%;
          left: 20px;
          right: 20px;
          background-color: black;
          padding: 20px;
          color: #fff;
          transform: translateY(-50%);
      }

为什么要translateY(-50%) ?

因为使用定位进行移动时,位置是相对位置,如上面的top: 50%(main元素开启了相对定位,所以div参考自它的一半高度进行移动),移动后的div元素最顶"边框"与main元素的垂直中"线"重合。

如下只设置top: 50%;

center-top50.png

设置transform: translateY(-50%)后:

center-trans50.png

可以看到div元素相对于自己进行向上移动自身高度的50%以达到垂直居中。

方式三:

如果你不在乎container的高度被元素撑高的话,使用display: tabledisplay: table-cell或者使用html的table元素设置vertical-align: middle

html:

    <main>
        <div>
           I'm a block-level element with an unknown height, centered vertically within my parent.
        </div>
      </main>

CSS样式:

        body {
            font-size: 1em;
            background-color: #f06d6d;
        }

        main {
            background-color: white;
            height: 300px;
            margin: 20px;
            width: 300px;
            position: relative;
            padding: 20px;
            display: table;
        }
        
        main div {
            background-color: black;
            color: white;
            padding: 20px;
            display: table-cell;
            vertical-align: middle;
        }

效果:

center-block02.png

Flexbox

flexbox实现居中效果是最好的,也是比较简单的。

html:

    <main>
      <div>
        I'm a block-level element with an unknown height, centered vertically
        within my parent.
      </div>
    </main>

CSS样式:

      body {
        font-size: 1em;
        background-color: #fd6d6d;
      }

      main {
        display: flex;
        background-color: white;
        width: 300px;
        height: 300px;
        padding: 20px;
        margin: 20px;
        flex-direction: column;
        justify-content: center;
      }

      main div {
          background-color: black;
          color: white;
          padding: 20px;
      }

效果:

center-block03.png

Reference参考: