為什麼「margin:auto」可以讓塊級元素水平居中?
- 居中是如何計算的?
- 為何不能垂直居中?
瀉藥
這是個很老的問題了
貌似答案挺多的這誰葯偶來回答啊…… = =|||
不答又不合適簡單扯扯點其他貌似沒扯到的在 CSS 2 規範的 10 章 可視化布局內對 塊級非替換元素在普通流內布局有公式描述Visual formatting model details"margin-left" + "border-left-width" + "padding-left" + "width" + "padding-right" + "border-right-width" + "margin-right" = width of containing block
就是 左m+左b+左p+w+右p+右b+右m = 包含塊寬度
以及對這公式的 5 條 if跟這問題直接相關的是2個。先說第一個- 如果啊,width 是 auto 值,那麼其他是 auto 的值就為 0.
所以呢,先說 width auto margin auto 的時候啊,margin 就 0 了。
整個容器充滿包含塊唄。也就沒水平居中啥事兒了。然後呢,說水平居中的事兒。
這裡又有個if- 如果 "margin-left" "margin-right" 都是 auto 值,使用的值相等,那麼就水平居中包含塊。
基本上規定的死死了。
所以連起來就是:
如果有 width 那麼 ml/mr 是 auto(其他值么),那就是0,後面的一條 if 不生效了。如果 width 不是 auto,那就是有確定寬度了。 ml/mr 是 auto,那就居中。其實根據最初的公式很好理解,元素的包含塊寬度是最初能定下來。(你想啊,根 HTML 的包含塊不就是視口么,瀏覽起內窗口寬度啊,總能知道吧。然後根據這個初始包含塊寬度往下算)
所以,就有一系列確定值。確定標黑,不確定為(x),來說明 width,沒b沒p的情況(簡化下么)沒有的值標為 0"margin-left"(x) + "border-left-width"(0) + "padding-left"(0) + "width"(假設 300px) + "padding-right"(0) + "border-right-width" (0)+ "margin-right"(x) = width of containing block(假設 600 px)
整理下
x+0+0+300+0+0+x = 600求x2x+300 = 6002x = 300x = 150 (px)好了,ml 和 mr 就算出 150 px 了
(如果 其他 bl、br、pl、pr 有值就帶公式里,一樣的)排布下,正好容器在包含塊中間位置。這就是最後內個 if 要說的內容。為何不能垂直居中……
這個主要是規範里沒給這方面規定……並與其他初始設定衝突。如:width 相關計算依賴於其包含塊,這玩意是最初能確定值。而 height 相關計算依賴於其自身內容高度,自身內容高度是不能最初確定值的。所以無法建立類似上面的公式來使用 mt、mb auto 實現高度居中。
且,mt、mb 的百分比值參照還是依賴包含塊實際寬度的。同理,因為包含塊高度未知,沒辦法以確定值來計算 mt、mb。keyword auto默認是使用剩餘空間,所以不論left還是right定義了auto,計算值都會是包含塊的剩餘空間,如果左右都設置了auto,那麼就會均分剩餘空間。當然,這指的是書寫模式為lr-tb的情況下,這種情況,寬度是一定的。至於縱向,高度其實是沒有一個固定值,auto無可refer的參照物,如果top或bottom設置了auto,那計算值其實會是0。
這塊在標準里稱作「Calculating widths and margins」,講width/height,margin,left/right/top/bottom不同組合時的布局計算規則,具體鏈接如下:
http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins實際項目中,主要有兩種應用場景:
1、普通流布局通過「width&2、absolute元素在具體寬高容器中垂直水平居中對齊。
實現方式可參考下:CodePen - Absolute Centering詳細的計算規則看標準:http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
以上兩種場景,有一條規則是一樣的,無論垂直還是水平方向,margin有節餘同時對應方向設置了auto,相應方向計算出的margin是分半的(第一種垂直方向除外,why?標準規定!)。
因此,題主提到的垂直居中也是可以實現的,只是有了限制條件(應用場景二)。這個是轉自 @杜瑤 大神的博客(他也回答了 ,我就當幫他做個宣傳吧O(∩_∩)O~) ,這位大神寫了好多關於margin的使用技巧,我想下面這段可以解決樓主的問題吧~
正文開始
auto是margin的可選值之一。相信大家平時使用auto值時,最多的用法大概是 margin: 0 auto; 和 margin: auto;,恩,是的,塊元素水平居中。讓我們來看看代碼實現:
CSS:#demo{
width: 500px;
margin: auto; /* 或者 margin: 0 auto; */
}
HTML:
恩,我就是那個需要水平居中的傢伙。&&
&
為了更明顯點,我們來看個例子:margin實現塊元素水平居中。Cool,這麼簡單就實現了水平居中。
不過你可能也發現了不論是 margin: auto; 還是 margin: 0 auto; 效果都是一樣的,都是讓 #demo 水平居中了,但縱向並沒有任何變化。
大家都知道 margin 是複合屬性,也就是說 margin: auto; 其實相當於 margin: auto auto auto auto;,margin: 0 auto;相當於 margin: 0 auto 0 auto;,四個值分別對應上右下左。至於CSS中的上、右、下、左順序就不做贅述了。
根據規範,margin-top: auto; 和 margin-bottom: auto;,其計算值為0。這也就解釋了為什麼 margin: auto; 等同於 margin: 0 auto;。但僅此而已嗎?讓我們來看看規範描述:
原文:On the A edge and C edge, the used value of 『auto』 is 0.
翻譯:如果場景是A和C,那麼其 auto 計算值為 0。
更詳細請參閱:margin properties
由此可見,它們還與書寫模式 writing-mode 和 文檔流方向 direction 有關。所以我們說 margin: auto; 等同於 margin: 0 auto; 是不太精準的,因為還有前置條件。
了解這些很重要,這有助於理解 margin 屬性的設計意圖。
OK,聊了這麼多,我們回到默認的 writing-mode: horizontal-tb; 和 direction: ltr; 的情況繼續往下,後面的話題都基於這個前提。
為什麼auto能實現水平居中?這是因為水平方向的 auto,其計算值取決於可用空間(剩餘空間)。
原文:On the B edge and D edge, the used value depends on the available space.
翻譯:如果場景是B和D,那麼其 auto 計算值取決於可用空間。
CSS權威指南-chapter 7裡面有說到:
&> 正常流中的塊級元素框的水平總和就等於父元素的width
&> 在水平格式化的「7大屬性」中,只有3個可以設置為auto: width, margin-left, margin-right;因此, 只要我們設置了block element的width, 並且margin-leftauto; margin-right: auto; 就可以讓block element水平居中。
但是, 對於垂直格式化是不行的。
如果我們把margin-top和margin-right都設置為auto的話,實際上他們的高度將是0。(設定就是這樣吧- -),可以測試測試。想要垂直居中也可以, margin-top: 25%; margin-bottom: 25%; refrence: *css權威指南*我覺得這事兒就像要定義邊距為什麼要使用margin關鍵字,規則就是這樣的,沒有因為所以
以下答案並不是針對問題的回答
好像沒有人提到一種使 margin:auto; 能垂直水平居中的方法,還是說一下吧,萬一能幫到一些人
父元素: {
display: flex;
}
子元素: {
flex: 0 0 auto;
margin: auto;
}
就這樣。
因為CSS規範中說明了:一個有特定寬度的元素,若左右邊距為auto,瀏覽器會取它的容器和該容器的寬度之差,除以2,作為該元素的左邊距和右邊距
margin: auto是margin: auto auto auto auto的縮寫,左右都auto,寬度相等,並且儘可能撐大,那就是居中了
高度也可以居中啊width:x;height:x;left:0;right:0;top:0;bottom:0;margin:auto;就可以了
推薦閱讀:
※如何讓input裡面placeholder水平居中?
※css 使用display:inline-block的問題求解?
※現在國外做網站是用 DIV + CSS,還是 table?
※有哪些好的 HTML 和 CSS 入門教程可以推薦給新手?
※CSS3 中calc()關鍵字+(加)、-(減)運算符為何必須加空格?