# [css]水平垂直置中的方法
## 前言
HTML會根據網頁元素的種類去預設它的 display 屬性,網頁元素分為兩種:Block-level Element 和 Inline Element。
### Block-level Element (區塊元素)
會佔滿父元素的寬度,並且每次都是從新的一行開始。常見的 block-level elememt 有:
```
<div> <figure> <form> <h1>~<h6> <header> <li> <main> <nav>
<ul> <ol> <p> <section> <table>
```
### Inline Element (行內元素)
不會換行,而且會自適應內容大小,但是不能夠設定 width、height、margin、background-img…等。常見的inline element 有:
```
<a> <button> <em> <i> <img> <label> <select> <span> <strong> <textarea>
```
**vertical-align 只適用於行內元素與表格**
### Display: inline-block
inline-block 同時擁有 bock-level element 和 inline element 的特性:它的外在是 inline,而內在是 block 。
因為外在是inline,所以它不會換行而且會自適應內容大小,但內在像 block,因此它可以設定 width、height、margin、backgound-img…等參數。
## 7種水平垂直置中的方法
### 1.設定行高 ( line-height )
設定行高是垂直置中最簡單的方式,適用於「單行」的「行內元素」 ( inline、inline-block ),例如:單行的標題,或是已經設為 inline-block 屬性的 div。
若將 **line-height 設成和高度一樣的數值**,則內容的行內元素就會被垂直置中,**因為是行高,所以會在行內元素的上下都加上行高的 1/2**。
:::info
如果為多行,第二行與第一行的間距會變超大,不是我們所期望的效果。
:::
```jsx=
//HTML
<div class="parent">
<span class="child">I'm vertically/horizontally centered!</span>
</div>
//CSS
.parent {
height: 200px;
width: 400px;
background: lightgray;
text-align: center;
}
.parent > .child {
line-height: 200px;
}
```
### 2.添加偽元素
將 :before 偽類物件設定為 100% 高的 inline-block,再搭配上需要垂直對齊的div同樣設定成 inline-block 屬性後,就能對兩者使用 vertical-align: middle 來達到 :before 與 inline-block 內容物件垂直對齊的目的。
```jsx=
//HTML
<div class="box box3">
<div class="content"></div>
</div>
//CSS
.box{
width: 500px;
height: 250px;
border: 1px solid;
margin: auto;
text-align: center;
}
.box::before{
content:'';
display: inline-block;
height: 100%;
width: 0;
vertical-align: middle;
}
.box .content{
width: 400px;
height:100px;
background: #ccc;
display: inline-block;
vertical-align: middle;
}
```
### 3.calc 動態計算
如果div 必須要是 block,這時候就可以用 calc動態計算來達成。
使要置中的 div 的 top 屬性,與上方的距離是「50% 的外框高度 + 50% 的 div 高度」,就可以做到垂直置中。
:::info
為什麼不用 margin-top,因為 margin 抓到的是水平寬度,必須要用 top 才會正確。
:::
```jsx=
//HTML
<div class="container">
<div class="content">
</div>
</div>
//CSS
.container{
width: 500px;
height: 250px;
border: 1px solid #f00;
margin:auto
}
.content{
width: 400px;
height: 70px;
top:calc((100% - 70px) / 2);
margin:auto;
background: #ccc;
position: relative;
}
```
### 4.使用表格(使用Table屬性)
將div的display 屬性設定成表格的儲存格(td),這樣就能利用支援儲存格垂直對齊的 vertical-align: middle 屬性來將資料垂直置中。
```jsx=
//HTML
<div class="box box19">
<div class="content">
I'm vertically/horizontally centered!
</div>
</div>
//CSS
.box{
width: 500px;
height: 250px;
border: 1px solid;
margin: auto;
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content{
width: 400px;
background: #ccc;
margin: auto;
}
```
### 5.transform
transform 是 CSS3 的新屬性,主要掌管元素的變形、旋轉和位移,利用 transform 裏頭的 translateY ( 改變垂直的位移,如果使用百分比為單位,則是以元素本身的長寬為基準 ),搭配元素本身的 top 屬性(Top: 50% ,讓物件上方能產生固定%數的距離),就可以做出垂直置中的效果。
```jsx=
//HTML
<div class="box box21">
<div class="content">
I'm vertically/horizontally centered!
</div>
</div>
//CSS
.box{
width: 500px;
height: 250px;
border: 1px solid #f00;
margin: auto;
}
.content{
width: 400px;
background: #ccc;
position: relative;
top: 50%;
transform: translateY(-50%);
margin: auto;
}
```
### 6.絕對定位
使用 position:absolute 來指定位置,但垂直置中的做法和我們正統的絕對位置不太相同,**要將上下左右的數值都設為 0,再搭配一個margin:auto**,就可以辦到垂直置中。
(當物件設定絕對定位之後,預設它是抓不到整體可運用空間的範圍,所以 margin: auto 此時會失效,但當你設定了 top: 0; bottom: 0 時,絕對定位物件就抓到可運用的空間了,這時你的 margin: auto 就生效了)
:::info
設定position:absolute的子元素,父元素必須要指定position: relative!另外,絕對定位的元素會互相覆蓋的,所以如果內容元素較多,可能就會有些問題出現。
:::
```jsx=
//HTML
<div class="container">
<div></div>
</div>
//CSS
.container{
position: relative;
width:500px;
height:200px;
border:1px solid #000;
}
.container div{
position: absolute;
width:250px;
height:100px;
top:0;
right:0;
bottom:0;
left:0;
margin:auto;
background:#f60;
}
```
### 7.使用 Flexbox
設定父層 display: flex,使用 align-items 和 justify-content 的屬性,就可以做到垂直置中的效果喔!
```jsx=
//HTML
<div class="box box7">
<div class="content">
I'm vertically/horizontally centered!
</div>
</div>
//CSS
.box{
width: 500px;
height: 250px;
border: 1px solid ;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
}
.content{
width: 400px;
background: #ccc;
}
```
[方法展示](https://jsbin.com/vibahagike/edit?html,css,output)
[5 ways to align HTML element horizontally and vertically](https://dev.to/b3ns44d/5-ways-to-align-html-element-horizontally-and-vertically-2fnc)
[[30 道難解的 CSS 排版] 第 1 道:認識對齊 I](https://ithelp.ithome.com.tw/articles/10213624)
[CSS 垂直置中的三個方法](https://www.oxxostudio.tw/articles/201408/css-vertical-align.html)
[CSS垂直置中技巧,我只會23個,你會幾個](http://csscoke.com/2018/08/21/css-vertical-align/)