背景
在開發中經常遇到這個問題,即讓某個元素的內容在水平和垂直方向上都居中,內容不僅限于文字,可能是圖片或其他元素
居中是一個非常基礎但又是非常重要的應用場景,實現居中的方法存在很多,可以將這些方法分成兩個大類:
- 居中元素(子元素)的寬高已知
- 居中元素寬高未知
實現方式
以下是10種實現元素水平垂直居中的方式:
- text-align:center 塊狀元素,水平居中(只適用于塊級元素,塊級元素內的行內元素可以居中或者將此行內元素設置為塊級元素)
- margin:0 auto 水平居中 以外邊框為參照物,上下外邊框距為0,左右外邊框距瀏覽器會自動計算平分
- line-height 垂直居中 通過設置行間距。line-height只適用于單行文本的元素,多行元素不適用。
- float屬性+relative定位 給父元素設置float:left ,然后父元素整體向左移動50%(position:relative;left:50%),這時父元素要清除浮動(clear:both),然后再給子元素整體向左移動50%(position:relative;left:-50%)
- 根據絕對定位absolute+margin實現水平居中 給父元素一個相對定位relative,利用絕對定位absolute,配合margin:auto自動計算外邊距(position: absolute; top: 0;right: 0; bottom: 0; left: 0;margin: auto;)。相對于相對應于relative的絕對定位absolute,需要定寬。relative只是為了給子元素定位用的
- 使用absolute絕對定位+translate 移動轉換,實現水平垂直居中 使用百分比來絕對定位一個元素,并配合使用translate,將元素移動定位居中(position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%))。
- 利用table布局,默認垂直居中(vertical-align:middle) 如果不是table布局的話可以:仿table(display:table-cell),一樣使用vertical-align:middle實現居中對齊
- flex布局 父元素使用display:flex,設置其屬性justify-content.align-items都為center(display: flex; justify-content: center; align-items: center),實現水平居中
- flex布局+margin 父元素使用flex布局(display:flex),子元素使用margin:auto
- 利用定位+margin:負值
- grid布局
絕對定位+transform:translate(-50%,-50%)
.parent{ position:relative;}.son{ position: absolute; top:50%; left:50%; transform:translate(-50%,-50%);}
行內元素
基本思想:單行文本子元素line-height 值為父元素 height 值
.parent { height: 200px;}.son { line-height: 200px;}
行內塊級元素
基本思想:元素是行內塊級,使用display: inline-block, vertical-align: middle+偽元素處于容器中央
.parent::after, .son{ display:inline-block; vertical-align:middle;}.parent::after{ content:''; height:100%;}
利用定位+margin:auto
先上代碼:
<style> .father{ width:500px; height:300px; border:1px solid #0a3b98; position: relative; } .son{ width:100px; height:40px; background: #f0a238; position: absolute; top:0; left:0; right:0; bottom:0; margin:auto; }</style><div class="father"> <div class="son"></div></div>
父級設置為相對定位,子級絕對定位 ,并且四個定位屬性的值都設置了0,那么這時候如果子級沒有設置寬高,則會被拉開到和父級一樣寬高
這里子元素設置了寬高,所以寬高會按照我們的設置來顯示,但是實際上子級的虛擬占位已經撐滿了整個父級,這時候再給它一個margin:auto它就可以上下左右都居中了
利用定位+margin:負值
絕大多數情況下,設置父元素為相對定位, 子元素移動自身50%實現水平垂直居中
<style> .father { position: relative; width: 200px; height: 200px; background: skyblue; } .son { position: absolute; top: 50%; left: 50%; margin-left:-50px; margin-top:-50px; width: 100px; height: 100px; background: red; }</style><div class="father"> <div class="son"></div></div>
整個實現思路如下圖所示:
- 初始位置為方塊1的位置
- 當設置left、top為50%的時候,內部子元素為方塊2的位置
- 設置margin為負數時,使內部子元素到方塊3的位置,即中間位置
這種方案不要求父元素的高度,也就是即使父元素的高度變化了,仍然可以保持在父元素的垂直居中位置,水平方向上是一樣的操作
但是該方案需要知道子元素自身的寬高,但是我們可以通過下面transform屬性進行移動
利用定位+transform
實現代碼如下:
<style> .father { position: relative; width: 200px; height: 200px; background: skyblue; } .son { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 100px; height: 100px; background: red; }</style><div class="father"> <div class="son"></div></div>
translate(-50%, -50%)將會將元素位移自己寬度和高度的-50%
這種方法其實和最上面被否定掉的margin負值用法一樣,可以說是margin負值的替代方案,并不需要知道自身元素的寬高
table布局
設置父元素為display:table-cell,子元素設置 display: inline-block。利用vertical和text-align可以讓所有的行內塊級元素水平垂直居中
<style> .father { display: table-cell; width: 200px; height: 200px; background: skyblue; vertical-align: middle; text-align: center; } .son { display: inline-block; width: 100px; height: 100px; background: red; }</style><div class="father"> <div class="son"></div></div>
flex彈性布局
還是看看實現的整體代碼:
<style> .father { display: flex; justify-content: center; align-items: center; width: 200px; height: 200px; background: skyblue; } .son { width: 100px; height: 100px; background: red; }</style><div class="father"> <div class="son"></div></div>
css3中了flex布局,可以非常簡單實現垂直水平居中
這里可以簡單看看flex布局的關鍵屬性作用:
- display: flex時,表示該容器內部的元素將按照flex進行布局
- align-items: center表示這些元素將相對于本容器水平居中
- justify-content: center也是同樣的道理垂直居中
2012版寫法
.parent{ display:flex; justify-content:center;}.son{ align-self:center;}
grid網格布局
<style> .father { display: grid; align-items:center; justify-content: center; width: 200px; height: 200px; background: skyblue; } .son { width: 10px; height: 10px; border: 1px solid red }</style><div class="father"> <div class="son"></div></div>
這里看到,gird網格布局和flex彈性布局都簡單粗暴
小結
上述方法中,不知道元素寬高大小仍能實現水平垂直居中的方法有:
- 利用定位+margin:auto
- 利用定位+transform
- flex布局
- grid布局
總結
根據元素標簽的性質,可以分為:
- 內聯元素居中布局
- 塊級元素居中布局
內聯元素居中布局
水平居中
- 行內元素可設置:text-align: center
- flex布局設置父元素:display: flex; justify-content: center
垂直居中
- 單行文本父元素確認高度:height === line-height
- 多行文本父元素確認高度:display: table-cell; vertical-align: middle
塊級元素居中布局
水平居中
- 定寬: margin: 0 auto
- 絕對定位+left:50%+margin:負自身一半
垂直居中
- position: absolute設置left、top、margin-left、margin-top(定高)
- display: table-cell
- transform: translate(x, y)
- flex(不定高,不定寬)
- grid(不定高,不定寬),兼容性相對比較差