Margin折疊,站在設(shè)計(jì)者的角度思考

2018-02-24 15:22 更新

Margin折疊,站在設(shè)計(jì)者的角度思考

原作者:melon
原文地址:http://melonh.com/css/2015/04/28/understand-margin-collapse.html

大部分前端開發(fā)者在實(shí)現(xiàn)布局時(shí),都會(huì)遇到Margin折疊的問題。CSS2.1標(biāo)準(zhǔn)文檔中對(duì)Margin折疊的規(guī)則進(jìn)行了標(biāo)準(zhǔn)的描述,但卻沒有解釋這樣設(shè)計(jì)的原因。使得我們想要摸清楚Margin折疊規(guī)則變得異常困難,通常需要死記硬背。 博主本人非常懶,這兩天終于下定決心動(dòng)動(dòng)瓜腦子研究透徹Margin折疊。本篇文章我試圖站在設(shè)計(jì)者的角度思考Margin折疊的設(shè)計(jì)思想,幫助自己和大家一起理解Margin折疊,拋開那些死記硬背。

標(biāo)準(zhǔn)文檔對(duì)Margin的規(guī)定

首先,我們看看標(biāo)準(zhǔn)文檔對(duì)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.

翻譯:外邊距用來指定非浮動(dòng)元素與其周圍盒子邊緣的最小距離。兩個(gè)或兩個(gè)以上的相鄰的垂直外邊距會(huì)被折疊并使用它們之間最大的那個(gè)外邊距值。多數(shù)情況下,折疊垂直外邊距可以在視覺上顯得更美觀,也更貼近設(shè)計(jì)師的預(yù)期。

注意: 如文檔所說,margin是非浮動(dòng)元素與周圍盒子邊緣的“最小”邊距哦。它定義的只是外邊距的最小值。

為什么要有Margin折疊?

只有垂直Margin會(huì)發(fā)生折疊,而水平Margin則不會(huì)。這是為了排版的需要,因?yàn)樵诙鄶?shù)情況下,折疊垂直外邊距可以在視覺上顯得更美觀,也更貼近設(shè)計(jì)師的預(yù)期。

Margin折疊規(guī)則

這里列出標(biāo)準(zhǔn)文檔中的Margin折疊規(guī)則??焖贋g覽即可:

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.

翻譯: 兩個(gè)Margin當(dāng)且只有符合以下規(guī)則時(shí),才會(huì)發(fā)生折疊: 1. 都屬于文檔流中的塊級(jí)盒子,并且屬于同一個(gè)BFC。 2. 無line box, clearance, padding, border分離它們 3. 都屬于垂直相鄰的盒子邊界
以上的規(guī)則暗示了: 1. 浮動(dòng)盒子不會(huì)跟其它盒子發(fā)生margin折疊(即使是于它的子元素)。 2. 創(chuàng)建BFC的盒子(如浮動(dòng)根元素和overflow不為visible的元素)的Margin不會(huì)跟它的子元素發(fā)生margin折疊。 3. 絕對(duì)定位的盒子不會(huì)發(fā)生margin折疊(即使與它的子元素)。 4. display為inline-block的元素不會(huì)發(fā)生margin折疊(即使與它的子元素)。 5. 文檔流中的會(huì)計(jì)元素的bottom margin總會(huì)和它的下一個(gè)文檔流中的兄弟元素的top margin折疊,除非這個(gè)兄弟元素有clearance 6. 如果文檔流中一個(gè)元素沒有top border, top padding,且它的子元素沒有clearance,那么它的top margin會(huì)與它的第一個(gè)文檔流中的塊級(jí)子元素的top margin折疊。 7. 如果文檔流中的一個(gè)元素的高度為auto,min-height為0,且它沒有bottom padding和bottom border,且它的子元素的bottom margin沒有與擁有 8. 當(dāng)一個(gè)盒子的min-height為0,沒有top或bottom borders,沒有top或bottom padding,height為0或auto,不包含line box,且它的所有文檔流中的子孫元素的margin都折疊了,那么它自己的top margin和bottom margin會(huì)折疊。

Margin設(shè)計(jì)思想-我的理解

  1. 只有文檔流中的塊級(jí)元素會(huì)發(fā)生Margin折疊 文檔流外的元素,我們將它們看作是希望有特殊定位的元素,不應(yīng)該應(yīng)用文檔流中常規(guī)文檔的排版規(guī)則。因此, float不為none,或者position為absolute的元素,不會(huì)與兄弟元素發(fā)生margin折疊。

    display為inline-block的元素參與渲染上下文是Inline block center。其垂直位置不僅依賴于Margin,還依賴于自己所屬的line box。因此也不應(yīng)發(fā)生margin折疊。

  2. 創(chuàng)建BFC的元素,不會(huì)與子元素發(fā)生margin折疊

BFC(Block formatting context)直譯為"塊級(jí)格式化上下文"。它是一個(gè)獨(dú)立的渲染區(qū)域,只有Block-level box參與, 它規(guī)定了內(nèi)部的Block-level Box如何布局,并且與這個(gè)區(qū)域外部毫不相干。

如標(biāo)準(zhǔn)文檔所說,BFC是一個(gè)獨(dú)立的渲染區(qū)域,它內(nèi)部的元素與這個(gè)區(qū)域外毫不相干,不會(huì)相互影響。因此,創(chuàng)建BFC元素ElementA,它的子元素的margin,不應(yīng)該影響ElementA與其兄弟元素或父元素之間的間距。

所以,符合以下條件觸發(fā)BFC的元素,都不會(huì)與自己的子元素發(fā)生margin折疊:

  • float屬性不為none
  • position為absolute或fixed
  • display為inline-block, table-cell,
  • table-caption, flex, inline-flex
  • overflow不為visible
  1. 當(dāng)元素之間產(chǎn)生間隙時(shí),可能不會(huì)發(fā)生margin折疊 元素之間可能由如下原因產(chǎn)生間隙:

    1. 兩個(gè)元素的margin之間存在border或padding阻擋時(shí),兩個(gè)元素的margin無法折疊。
    2. 兩個(gè)元素相鄰,第二個(gè)元素由于設(shè)置了clear不為none,被浮動(dòng)的元素?cái)D下去,與第一個(gè)元素的margin可能折疊不完全,或者不折疊。

防止Margin折疊

如上所說:

  1. 只有文檔流中的塊級(jí)元素會(huì)發(fā)生Margin折疊 因此可通過將元素從文檔流中去除,或者display設(shè)為inline-block的方式,防止其與兄弟節(jié)點(diǎn)發(fā)生margin折疊。
  2. 創(chuàng)建BFC的元素,不會(huì)與子元素發(fā)生margin折疊 因此可通過觸發(fā)元素的BFC,來防止它與自己的子元素發(fā)生Margin折疊
  3. 當(dāng)元素之間產(chǎn)生間隙時(shí),可能不會(huì)發(fā)生margin折疊 因此可通過padding,border來制造間隙,以防止margin折疊

總結(jié)

這篇文章是我試圖站在設(shè)計(jì)者的角度,對(duì)Margin折疊設(shè)計(jì)思想的理解。避免死記硬背這些規(guī)則。大家如果有不同的理解,歡迎討論。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)