# 各种垂直居中总结

> 这里总结各种垂直居中的方法。重点是在不知道宽高的情况下如何设置垂直居中。面试和平时工作会常用到，尤其是flex布局的垂直居中法将在未来会成为主流。

## 确保只有一行文字的垂直居中

```html
.wrap-text {
    line-height: 100px;
    text-align: center;
    height: 100px;
    background-color: red;
}

<div class='wrap-text'>
    <p>只适合纯文本且只有一行</p>
</div>
```

关键点在于line-height的属性值要和父元素的高度相等，且文本只能一行。

## padding法垂直居中

```html
.wrap-padding {
    width: 400px;
    height: 200px;
    background-color: blue;
}

.wrap-padding-content {
    width: 100px;
    height: 100px;
    padding: 50px 150px;
    background-color: green;
    background-clip: content-box;
}

<div class="wrap-padding">
    <div class="wrap-padding-content"></div>
</div>
```

在子元素中，padding的属性值：上下=(父元素高度-子元素高度)/2;左右=(父元素宽度-子元素宽度度)/2，即50=(200-100)/2 150=(400-100)/2.且要设置background-clip的属性值为content-box.此方法**需要知道父元素的宽高**。

## margin法垂直居中

```html
.wrap-margin {
    overflow: hidden; 
    width: 400px;
    height: 200px;
    background-color: pink;
}

.wrap-margin-content {
    width: 100px;
    height: 100px;
    /* 50=(200-100)/2 左右设为auto margin-bottom设为0 */
    margin: 50px auto 0 auto;
    background-color: orange;
}

<div class="wrap-margin">
    <div class="wrap-margin-content"></div>
</div>
```

此方法需要在父元素设置overflow的属性值为hidden ，且子元素的margin-top的值=(父元素高度-子元素高度)/2,margin-left和margin-right设为auto, margin-bottom设为0.此方法**需要知道父元素的宽高**。

## 父元素设为相对对位，子元素设为绝对定位（但需要用到子元素的宽高）

```html
.wrap-relative {
    position: relative;
    width: 400px;
    height: 200px;
    background-color: coral;
}

.wrap-absolute-content {
    position: absolute;
    width: 100px;
    height: 100px;
    /* 先让top和left设为50% */
    top: 50%;
    left: 50%;
    /*这里的-50px是子元素宽高的一半*/
    margin-top: -50px;
    margin-left: -50px;
    background-color: #fff;
}

<div class="wrap-relative">
    <div class="wrap-absolute-content"></div>
</div>
```

父元素设为相对对位，子元素设为绝对定位，子元素的top和left的属性值设为50%,并且margin-top的属性值设为(-子元素的高度/2)，即-50px;margin-left的属性值设为(-子元素的宽度度/2)，即-50px.**这里就不用关心父元素的宽高**，但仍然要计算子元素的宽高，牙败牙败。

## 父元素设为相对对位，子元素设为绝对定位（无需知道任何元素的宽高）

```html
.wrap-relative-1 {
    position: relative;
    width: 400px;
    height: 200px;
    background-color: black;
}

.wrap-absolute-content-1 {
    position: absolute;
    width: 100px;
    height: 100px;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    background-color: #f2f2f2;
}

<div class="wrap-relative-1">
    <div class="wrap-absolute-content-1"></div>
</div>
```

这里将父元素设为相对对位，子元素设为绝对定位，而子元素的top, right, bottom, left的属性值都设为0, 且margin设为auto.这里**无需关注任何相关元素的宽高**。撒花 (✿◕‿◕✿)

## 父元素设为相对对位，子元素设为绝对定位（利用CSS3新属性，无需知道任何元素的宽高）

```html
.wrap-relative-2 {
    position: relative;
    width: 400px;
    height: 200px;
    background-color: yellow;
}

.wrap-absolute-content-2 {
    position: absolute;
    width: 100px;
    height: 100px;
    left: 50%;
    top: 50%;
    transform: translate3d(-50%, -50%, 0);
    background-color: purple;
}

<div class="wrap-relative-2">
    <div class="wrap-absolute-content-2"></div>
</div>
```

这里利用了CSS3的新属性，先将父元素设为相对对位，子元素设为绝对定位。子元素的left和top的属性值分别设为50%，并且将 transform的属性值设为translate3d(-50%, -50%, 0).

## 憋大招 弹性布局垂直居中

```html
.container {
    display: flex;
    /* 垂直居中 */
    align-items: center;
    /* 水平居中 */
    justify-content: center;
    width: 400px;
    height: 200px;
    background-color: black;
}

.item {
    width: 100px;
    height: 100px;
    background-color: pink;
}

*********************************************

/* 还可以这样写 */
.container {
    display: flex;
    width: 400px;
    height: 200px;
    background-color: black;
}

.item {
    width: 100px;
    height: 100px;
    margin: auto;
    background-color: pink;
}


<div class="container">
    <div class="item"></div>
</div>
```

这大抵是垂直居中的最优解决方案了，我在另一篇文章，[弹性布局](https://www.yanceyleo.com/blog/CSS/flexible-box/)介绍了弹性布局的常见属性。

## PS：

vh布局方式可以让元素相对于视口居中，特别是模态框这种东西更加适合，尤其在HTNML5.2新标准中增加了dialog标签之后。

```html
dialog {
    position: fixed;
    margin-top: 50vh;
    margin-left: 50vw;
    transform: translate(-50%, -50%);
}

<dialog open>
    <h1>我是模态框</h1>
    用户名：<input type="text"><br>


    密码：<input type="password"><br data-tomark-pass>
    提交：<input type="submit">
</dialog>

/*这里假定一个高度，因为dialog的position设为了fixed，因为无论鼠标滚轮怎么变化，模态框都是相对于视口垂直居中*/

/*而且卧槽，浏览器窗口在resize时，仍然能保持垂直居中，js可以拜拜了*/
<div style="height: 1000px"></div>
```

*注意：截至目前只有Chrome支持了dialog标签吼~*


---

Source: https://yanceyleo.com/post/824d3c83-5ae3-4199-b06d-9f634ab963d3
Published: 2018-06-15
Tags: CSS, CSS 垂直居中