原作者:melon
原文地址:http://melonh.com/css/2015/04/28/understand-margin-collapse.html
大部分前端開發(fā)者在實現(xiàn)布局時,都會遇到Margin折疊的問題。CSS2.1標準文檔中對Margin折疊的規(guī)則進行了標準的描述,但卻沒有解釋這樣設(shè)計的原因。使得我們想要摸清楚Margin折疊規(guī)則變得異常困難,通常需要死記硬背。 博主本人非常懶,這兩天終于下定決心動動瓜腦子研究透徹Margin折疊。本篇文章我試圖站在設(shè)計者的角度思考Margin折疊的設(shè)計思想,幫助自己和大家一起理解Margin折疊,拋開那些死記硬背。
首先,我們看看標準文檔對Margin的定義:
原文:The width of the margin on non-floating block-level elements specifies the minimum distance to the edges of surrounding boxes. Two or more adjoining vertical margins (i.e., with no border, padding or content between them) are collapsed to use the maximum of the margin values. In most cases, after collapsing the vertical margins the result is visually more pleasing and closer to what the designer expects.
翻譯:外邊距用來指定非浮動元素與其周圍盒子邊緣的最小距離。兩個或兩個以上的相鄰的垂直外邊距會被折疊并使用它們之間最大的那個外邊距值。多數(shù)情況下,折疊垂直外邊距可以在視覺上顯得更美觀,也更貼近設(shè)計師的預(yù)期。
注意: 如文檔所說,margin是非浮動元素與周圍盒子邊緣的“最小”邊距哦。它定義的只是外邊距的最小值。
只有垂直Margin會發(fā)生折疊,而水平Margin則不會。這是為了排版的需要,因為在多數(shù)情況下,折疊垂直外邊距可以在視覺上顯得更美觀,也更貼近設(shè)計師的預(yù)期。
這里列出標準文檔中的Margin折疊規(guī)則。快速瀏覽即可:
Two margins are adjoining if and only if: 1. both belong to in-flow block-level boxes that participate in the same block formatting context 2. no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.) 3. both belong to vertically-adjacent box edges, i.e. form one of the following pairs: top margin of a box and top margin of its first in-flow child bottom margin of box and top margin of its next in-flow following sibling bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', zero or 'auto' computed 'height', and no in-flow children
Note the above rules imply that: 1. Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children). 2. Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children. 3. Margins of absolutely positioned boxes do not collapse (not even with their in-flow children). 4. Margins of inline-block boxes do not collapse (not even with their in-flow children). 5. The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling, unless that sibling has clearance. 6. The top margin of an in-flow block element collapses with its first in-flow block-level child's top margin if the element has no top border, no top padding, and the child has no clearance. 7. The bottom margin of an in-flow block box with a 'height' of 'auto' and a 'min-height' of zero collapses with its last in-flow block-level child's bottom margin if the box has no bottom padding and no bottom border and the child's bottom margin does not collapse with a top margin that has clearance. 8. A box's own margins collapse if the 'min-height' property is zero, and it has neither top or bottom borders nor top or bottom padding, and it has a 'height' of either 0 or 'auto', and it does not contain a line box, and all of its in-flow children's margins (if any) collapse.翻譯: 兩個Margin當且只有符合以下規(guī)則時,才會發(fā)生折疊: 1. 都屬于文檔流中的塊級盒子,并且屬于同一個BFC。 2. 無line box, clearance, padding, border分離它們 3. 都屬于垂直相鄰的盒子邊界
以上的規(guī)則暗示了: 1. 浮動盒子不會跟其它盒子發(fā)生margin折疊(即使是于它的子元素)。 2. 創(chuàng)建BFC的盒子(如浮動根元素和overflow不為visible的元素)的Margin不會跟它的子元素發(fā)生margin折疊。 3. 絕對定位的盒子不會發(fā)生margin折疊(即使與它的子元素)。 4. display為inline-block的元素不會發(fā)生margin折疊(即使與它的子元素)。 5. 文檔流中的會計元素的bottom margin總會和它的下一個文檔流中的兄弟元素的top margin折疊,除非這個兄弟元素有clearance 6. 如果文檔流中一個元素沒有top border, top padding,且它的子元素沒有clearance,那么它的top margin會與它的第一個文檔流中的塊級子元素的top margin折疊。 7. 如果文檔流中的一個元素的高度為auto,min-height為0,且它沒有bottom padding和bottom border,且它的子元素的bottom margin沒有與擁有 8. 當一個盒子的min-height為0,沒有top或bottom borders,沒有top或bottom padding,height為0或auto,不包含line box,且它的所有文檔流中的子孫元素的margin都折疊了,那么它自己的top margin和bottom margin會折疊。
只有文檔流中的塊級元素會發(fā)生Margin折疊 文檔流外的元素,我們將它們看作是希望有特殊定位的元素,不應(yīng)該應(yīng)用文檔流中常規(guī)文檔的排版規(guī)則。因此, float不為none,或者position為absolute的元素,不會與兄弟元素發(fā)生margin折疊。
display為inline-block的元素參與渲染上下文是Inline block center。其垂直位置不僅依賴于Margin,還依賴于自己所屬的line box。因此也不應(yīng)發(fā)生margin折疊。
BFC(Block formatting context)直譯為"塊級格式化上下文"。它是一個獨立的渲染區(qū)域,只有Block-level box參與, 它規(guī)定了內(nèi)部的Block-level Box如何布局,并且與這個區(qū)域外部毫不相干。
如標準文檔所說,BFC是一個獨立的渲染區(qū)域,它內(nèi)部的元素與這個區(qū)域外毫不相干,不會相互影響。因此,創(chuàng)建BFC元素ElementA,它的子元素的margin,不應(yīng)該影響ElementA與其兄弟元素或父元素之間的間距。
所以,符合以下條件觸發(fā)BFC的元素,都不會與自己的子元素發(fā)生margin折疊:
當元素之間產(chǎn)生間隙時,可能不會發(fā)生margin折疊 元素之間可能由如下原因產(chǎn)生間隙:
如上所說:
這篇文章是我試圖站在設(shè)計者的角度,對Margin折疊設(shè)計思想的理解。避免死記硬背這些規(guī)則。大家如果有不同的理解,歡迎討論。
更多建議: