轉載 csdn
作者:buct-klx
原文鏈接:https://blog.csdn.net/qq_38164763/article/details/91360196
1、問題由來
如何居中一直是前端開發一個比較有意思的問題,估計每個做前端開發的人都能說出幾種方法來。但是不知道各位有沒有想過背後更深一點的東西。下面我將藉着本篇博客對使用margin居中的問題闡述一下自己的見解。
2、如何居中
水平居中
首先我們來討論一下水平居中的情況。
實現起來非常簡單,使用margin:0 auto即可,我們看如下代碼
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.center {
margin: 0 auto;
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body style="border: 1px solid black;">
<div class="center">
hello world
</div>
</body>
</html>
得到的效果如下
這樣這個div就被我們居中了,下面我們稍微修改一下代碼:
.center {
margin:0 auto;
/*width: 300px;*/
height: 300px;
/*background-color: red;*/
}
就變成了下面這樣
爲什麼居中的效果突然消失了?其實這個問題應該很容易想明白。我們在css樣式中去掉了寬度和背景色,那麼我們下面加上背景色來看看。
原來並不是div沒有居中,你可以理解爲div已經居中了,但是因爲你沒有設置寬度,所以div的寬度就變成了100%。那麼他的寬度爲什麼會變成100%呢?這就涉及到使用margin:0 auto居中的原理了。
使用maring:0 auto居中的原理
這涉及到一個名詞:橫向格式化屬性。那麼橫向格式化屬性是個什麼東西?他包含七個屬性:margin-left、border-left-width、padding-left、width、padding-rigth、border-right-width、margin-right,這七個屬性影響着塊級框的橫向佈局。他們七個的值加起來要等於元素容納塊的寬度,而這個寬度通常就是塊級父元素的width值。用公式來表示就是:
margin-left + border-left-width + padding-left + width + padding-rigth + border-right-width + margin-righ = width
這七個值中可以設置爲auto的值只有三個,margin-left、margin-right、width,如果把其中一個值設置爲auto,其他兩個值設置爲具體值,那麼設爲auto的那個屬性的具體長度要能滿足元素框的寬度等於父元素的寬度,即滿足那個等式。
那麼你可能會想,如果我把其中兩個設置爲auto呢?下面我們來討論這種情況:
把margin-left和margin-right全部設爲auto,width設置爲具體值,這時候兩個外邊距的長度相等,具體表現就是元素在父元素中居中顯示,也就是我們想要的水平居中效果。
把某一邊的外邊距和width設置爲auto,此時設置爲auto的外邊距等於0,寬度根據等式計算。舉個簡單的例子:
.center {
margin-left: 100px;
margin-right: auto;
width: auto;
height: 300px;
background-color: red;
}
此時我們將margin-right設置爲了auto,那它就會變成0,由於沒有設置border和padding,那麼他們默認爲0,所以width+margin-left應該等於父元素的寬度,這裏我的父元素就是body,所以表現出來應該就是margin-left等於100px然後div佔滿了剩下的空間,如圖
這就是設置兩個auto的情況。
那麼還有一種情況,我們把三個值全部設置爲auto,這時候會把左右邊距全部設置爲0,width則是要多寬有多寬。其實這就是我們在上面去掉寬度後顯示的結果。因爲去掉寬度後寬度的默認值就是auto,你又把左右邊距設置成了auto,那麼左右邊距自然變成0了,這也是爲什麼居中失效的原因。
接下來你可能會想,那我一個auto都不設置,全部設置成具體值,那你那個等式不就不成立了嗎?這種情況在css裏面被稱作過約束,在這種情況下margin-right會被強制設置爲auto。
垂直居中
瞭解完水平居中,我們現在來討論一下垂直居中。有了水平居中的經驗,你很容易這樣想,我垂直居中把它設置爲margin:auto 0不就行了嗎?真的是這樣嗎,我們來試一試
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.center {
margin: auto 0;
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div class="center">
hello world
</div>
</body>
</html>
他產生的效果是下面這樣的:
他爲什麼不會自動設置上邊距和下邊距?其實這跟auto的默認行爲有關,上下外邊距如果被設置爲auto,最終會變成0,就跟沒有外邊距是一樣的效果。這很容易想明白,父元素的高度都不確定,如何去自動居中?所以不可能像橫向margin那樣計算,這也就解釋了爲什麼我們不能使用auto來垂直居中元素。那麼我們如何來實現垂直居中?我們通常使用的代碼是下面這樣:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.father {
position: relative;
width: 500px;
height: 500px;
background-color: blue;
}
.center {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div class="father">
<div class="center"></div>
</div>
</body>
</html>
我們爲center元素加上絕對定位,並且把他的各個值全部設置爲0,這時神奇的事情發生了:
我們成功居中了子元素,那這又是什麼道理?其實此時在縱向上又存在一個等式:
top + margin-top + border-top-width + padding-top + height + padding-bottom + border-bottom-width + margin-bottom + bottom = height
在上面的式子中,top和bottom被設置成了0,margin等於auto,這時候瀏覽器爲了滿足這個等式會把上下的距離均勻分給margin,即達到我們想要的居中效果。同時橫向也是一樣的道理,所以我們可以看到其實這個元素是水平垂直居中,如果此時存在過約束,一般會忽略right屬性。