# 垂直居中

以下面例子为例说明，讲一个div居于页面中间

```markup
<div class="container">
    <div class="content">
        <div id="id1" class="border"></div>
        <div id="id2" class="border"></div>
    </div>
</div>
```

```markup
<style>
  body,html {
      margin: 0;
  }
  .container{
      margin: 0;
      width: 100%;
      height: 100%;
      position: relative;
  }
  .content{
      width: 400px;
      height: 200px;
      background: #CCCCCC;
      margin:auto;
  }
</style>
```

## **情况一**：在明确知道父元素与子元素的height属性值

```css
.container {
    height: 500px;
}

.content {
    width: 400px;
    height: 200px;
}
```

### 方法1： 父相对定位 + 子绝对定位 + 子 top margin-top定位

父元素使用相对定位，子元素使用绝对定位，使用top或者margin等改变位置的属性，设置为父元素高度的一半减去子元素高度的一半

```css
.content {
  /*方法一*/
  position: absolute;
  /*top: 150px;*/
  /*margin-top: 150px;*/
}
```

### 方法2： flex

```css
/*方法二： flex*/
.container{
    display: flex;
}
.content{
    // 在交叉轴场排列方式
  align-self:center;
}
```

## **情况二**：元素高度未知的情况

### 方法2： flex

**flex几乎是万能的**。继续使用flex，flex布局是CSS3中很有用的发明，尤其在局中的问题上，设置普通的样式不好解决的情况下，使用flex布局很容易解决，在以后使用的过程中，有限使用flex布局

```css
/*方法二： flex*/
.container{
    display: flex;
}
.content{
    align-self:center;
}
```

### **方法3**：使用JS获取相关高度，再添加定位样式

```markup
<script type="text/javascript">
    let father = document.getElementsByClassName('container')[0];
    let son = document.getElementsByClassName('content')[0];
    son.style.position= 'absolute';
    son.style.top= (father.offsetHeight-son.offsetHeight)/2 +'px' ;
</script>
```

### **方法4**：`transform: translate(-50%,-50%)` + `top,left: 50%`

注意： translate(x,y) 括号里填百分比数据的话，会以本身的长宽做参考，所以先将元素顶部通过定位移动到页面50%位置(`top: 50%`)，然后再对元素自身translate变换，移动自身50%。

* `translate`的参数是以元素自身宽高为参考的，因此需要先设置元素`top: 50%`，在设置top的时候，元素是绝对定位或者相对定位的，再使用`translate`将元素向上移动自身高度的50%。
* `transform`的使用对象是块级元素以及某些内联元素

```css
.content {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
}
```

### 方法5 ：vertical-align

使用`vertical-align`定义**行内元素**的基线相对于该元素所在行的基线的垂直对齐，这里有个很关键的概念叫做 `line-box`，此方法只针对于内嵌或者行内元素。使元素变为内联元素方法有两种，一种`display: inline-block`， 另一种是`display: table-cell`， 不同的display，`vertical-align: middle`作用对象不一样

#### 方法 5.1 ：vertical-align + inline-block

* 给父类添加after伪元素并`vertical-align: middle`,或者在最后添加一个空白子元素并`vertical-align: middle`，目的是为了将line-box线居中

```markup
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        .parent {
            height: 500px;
            background: #ccc;
        }
        .parent:after{
                    display: inline-block;
                    vertical-align: middle;
                    content: '';
                    height:100%;
                }
        .son {
            display: inline-block;
            background: #555555;
            margin:auto;
        }
    </style>
</head>
<body>
<div class="parent">
    <div class="son">居中元素</div>
</div>
</body>
</html>
```

#### 方法 5.2： vertical-align + table-cell

* 使用`display: table-cell`，table-cell 就是html中 `<td>`元素的特性， 可以让`vertical-align: middle`生效
* 给父元素display设置为table-cell，`vertical-align: middle;`,其其子元素就可以垂直居中了

```css
.parent {
    height: 500px;
    background: #ccc;
    display: table-cell;
    vertical-align: middle;
}
.son {
    background: #555555;
}
```

### 方法 6 : 绝对定位+margin：auto +  四个定位值

通过对确定宽高的的元素，相对其父元素定位，`top` `bottom` `left` `right`四个属性的值都设置为0， 通过margin：auto来对子元素进行位置的改变，这种方法原理其实就是靠`margin: auto`将剩余部分空间通过平分的方式填充了，自然就垂直水平居中了，

```markup
<h2>垂直居中 绝对定位方式</h2>
<div class="type2">
    <div class="type2-son">居中元素</div>
</div>
<style>
    .type2 {
        position: relative;
        height: 200px;
        background: yellow;
    }
    .type2-son {
        position: absolute;
        width: 100px;
        height: 20px;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: auto;
    }
</style>
```

绝对定位居中原理 ： [原理](https://www.zhangxinxu.com/wordpress/2013/11/margin-auto-absolute-%E7%BB%9D%E5%AF%B9%E5%AE%9A%E4%BD%8D-%E6%B0%B4%E5%B9%B3%E5%9E%82%E7%9B%B4%E5%B1%85%E4%B8%AD/)

### 方法7：line-height

`line-height`，这个使用也是有使用条件的。 在应用到一个块级元素时，它定义了该元素中基线之间的最小距离而不是最大距离。\
并且该属性还会被子元素继承。

## 总结：

综上所属：针对不确定高度

* 最好用的当然属于flex，有些人称之为终级杀器,既可以对单个元素垂直居中，又可以对多个元素垂直居中，
* 其次可以使用transform。注意要使用相对定位或者绝对定位在垂直方向上将元素下移50%。单个元素和多个兄弟元素都可以
* vertical-align定位的话要限制元素不能为块元素，单个元素和多个兄弟元素都可以，使用时要小心：
  * 给父类添加after伪元素并`vertical-align: middle`,或者在最后添加一个空白子元素并`vertical-align: middle`，目的是为了将line-box线居中
  * 使用`display: table-cell`，可以让`vertical-align: middle`生效，子元素垂直居中
* 绝对定位margin：auto + 四个定位值=0，这种方法原理其实就是靠`margin: auto`将剩余部分空间通过平分的方式填充了，自然就垂直水平居中了，对于单个元素使用起来很方便，推荐使用这种方法，但是对于多个元素，需要将多个元素用一个父元素包裹起来，再将父元素当做单个元素操作，结构上比上面的方法复杂了一点。
* line-height方法限制以及受影响的范围太多，不推荐
