CSS实现水平垂直居中的10种方式

前端面试必考题

Posted by Jerry on January 28, 2019

这是一道面试必考题!
这是一道面试必考题!
这是一道面试必考题!
最要的事情说三遍!

其实网上已经有了很多的该题教程,在这里只是想做个汇总,并且会将所有demo放在github上供大家直接使用,欢迎star

固定宽高的三种:

  • absolute + 负margin
  • absolute + margin auto
  • absolute + calc

自适应的七种:

  • absolute + transform
  • lineheight
  • writing-mode
  • table
  • css-table
  • flex
  • grid

10种实现方式预览,请点击

固定宽高

absolute + 负margin

实现原理:先absolute设置50%,然后负margin元素本身的一半宽高。

.demo {
    position: relative;
}
.vc1 {
    width:200px;
    height:200px;
    background-color: red;
    position: absolute;
    top:50%;
    left:50%;
    margin-top:-100px;
    margin-left:-100px;
}

<div class="demo">
    <div class="vc1"></div>
</div>

absolute + margin auto

实现原理:先absolute四个方向设置为0,然后设置margin为auto。

.demo {
    position: relative;
}
.vc2 {
    width:200px;
    height:200px;
    background-color: red;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}

<div class="demo">
    <div class="vc2"></div>
</div>

absolute + calc

实现原理:先absolute,然后top/left的值通过计算属性calc设置(50%-宽高/2)。

.demo {
    position: relative;
}
.vc3 {
    width:200px;
    height:200px;
    background-color: red;
    position: absolute;
    top: calc(50% - 100px);
    left: calc(50% - 100px);
}

<div class="demo">
    <div class="vc3"></div>
</div>

自适应

absolute + transform

实现原理:先absolute,然后top/left设置为50%,再利用translate位移拉回自身宽高的50%。

.demo {
    position: relative;
}
.vc4 {
    background-color: blue;
    position: absolute;
    top:50%;
    left:50%;
    transform: translate(-50%,-50%);
}

<div class="demo">
    <div class="vc4"></div>
</div>

lineheight

实现原理:外层设置行高并且text-align为center,内层inline-block后,继承行高。

.demo5 {
    width:100%;
    height: 500px;
    border:1px solid #ccc;
    box-sizing: border-box;
    color: #fff;
    line-height: 500px;
    text-align: center;
}
.vc5 {
    display: inline-block;
    background-color: blue;
    vertical-align: middle;
    line-height: initial;
    text-align: left;
}

<div class="demo5">
    <div class="vc5">lineheight</div>
</div>

writing-mode

实现原理:要分三层处理。第一层writing-mode为vertical-lr,文字竖放后居中做到垂直居中,第二层用horizontal-tb将文字转换回来,层级设置inline-block实现水平居中,最后一层inline-block且文字left。

.demo6 {
    width:100%;
    height: 500px;
    border:1px solid #ccc;
    box-sizing: border-box;
    color: #fff;
    writing-mode: vertical-lr;
    text-align: center;
}
.demo6-inner {
    writing-mode: horizontal-tb;
    display: inline-block;
    width: 100%;
}
.vc6 {
    background-color: blue;
    display: inline-block;
    text-align: left;
}

<div class="demo6">
    <div class="demo6-inner">
        <div class="vc6">writing-mode</div>
    </div>
</div>

table

实现原理:古老的table布局,利用td本身特性进行垂直居中。

.demo7 {
    width:100%;
    height: 500px;
    border:1px solid #ccc;
    box-sizing: border-box;
    color: #fff;
    text-align: center;
}
.vc7 {
    display: inline-block;
    background-color: blue;
}

<table cellpadding="0" cellspacing="0" class="demo7">
    <tbody>
    <tr>
        <td>
            <div class="vc7">table</div>
        </td>
    </tr>
    </tbody>
</table>

css-table

实现原理:利用css的方式,将div的display转成table-cell,就可以模拟td的特性,(最外层style只是为了设置外层宽度方便查看可忽略)

.demo8 {
    height: 500px;
    border:1px solid #ccc;
    color: #fff;
    box-sizing: border-box;
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}
.vc8 {
    display: inline-block;
    background-color: blue;
}

<div style="display:table;width: 100%">
    <div class="demo8">
        <div class="vc8">css-table</div>
    </div>
</div>

flex

实现原理:css3经典的flew布局。

.demo9 {
    width:100%;
    height: 500px;
    border:1px solid #ccc;
    box-sizing: border-box;
    color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
}
.vc9 {
    background-color: blue;
}

<div class="demo9">
    <div class="vc9">flex</div>
</div>

grid

实现原理:比较不常用的grid布局,可以通过子层的align-self和justify-self来做到垂直居中。

.demo10 {
    width:100%;
    height: 500px;
    border:1px solid #ccc;
    box-sizing: border-box;
    color: #fff;
    display: grid;
}
.vc10 {
    align-self: center;
    justify-self: center;
    background-color: blue;
}

<div class="demo10">
    <div class="vc10">grid</div>
</div>