- From: fantasai <fantasai.lists@inkedblade.net>
- Date: Wed, 28 Jul 2010 20:01:12 -0700
- To: "www-style@w3.org" <www-style@w3.org>
This is for CSS2.1 Issue 159 http://wiki.csswg.org/spec/css2.1#issue-159 triggered by this email http://lists.w3.org/Archives/Public/www-style/2010Feb/0015.html It turns out, margin collapsing is very straightforward to define. Most of the section is just giving examples of applying a small handful of rules. First, the complete reorganized text, which covers all but the last two paragraphs of 8.3.1. This should give an overview of where we're going. (Aside from a few minor editorial tweaks, all of the changes after "Note the above rules imply that" are merely shifting things around.) | In CSS, the adjoining margins of two or more boxes (which could be | next to one another or nested) can combine to form a single margin. | Margins that behave this way are called <dfn>collapsing margins</dfn>. | | Two margins are adjoining if and only if: | * no non-empty content, padding or border areas; line boxes; | or clearance separate them | * both belong to normal-flow block-level boxes in the same block | formatting context | | Note. Adjoining boxes may be generated by elements that are not | related as siblings or ancestors. | | Vertical margins collapse if they are adjoining. (Horizontal margins | never collapse.) However: | * Margins of the root element's box do not collapse. | * If the top and bottom margins of an element with clearance are | adjoining, its margins collapse with the adjoining margins of | subsequent siblings but that resulting margin does not collapse | with the bottom margin of the parent block. | | Note the above rules imply that: | * Vertical margins between a floated box and any other box do not | collapse (not even between a float and its in-flow children). | * Vertical 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. | * Margins of absolutely positioned boxes do not collapse (not even | with their in-flow children). | * Margins of inline-block elements do not collapse (not even with | their in-flow children). | * 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. | * 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. | * The bottom margin of an in-flow block element with a | 'height' of 'auto' collapses with its last in-flow block-level | child's bottom margin if the element has no bottom padding or | border. | * An element'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) are adjoining. | | When two or more margins collapse, the resulting margin width is the | maximum of the adjoining margin widths. In the case of negative | margins, the maximum of the absolute values of the negative adjoining | margins is deducted from the maximum of the positive adjoining margins. | If there are no positive margins, the absolute maximum of the negative | adjoining margins is deducted from zero. | | If the top and bottom margins of a box are adjoining, then it is | possible for margins to collapse through it. In this case, the | position of the element depends on its relationship with the other | elements whose margins are being collapsed. | * If the element's margins are collapsed with its parent's top | margin, the top border edge of the box is defined to be the | same as the parent's. | * Otherwise, either the element's parent is not taking part in | the margin collapsing, or only the parent's bottom margin is | involved. The position of the element's top border edge is | the same as it would have been if the element had a non-zero | bottom border. | Note that the positions of elements that have been collapsed through | have no effect on the positions of the other elements with whose | margins they are being collapsed; the top border edge position is | only required for laying out descendants of these elements. Now for the breakdown: Replaced # In this specification, the expression collapsing margins means # that adjoining margins (no non-empty content, padding or border # areas or clearance separate them) of two or more boxes (which # may be next to one another or nested) combine to form a single # margin. with | In CSS, the adjoining margins of two or more boxes (which could be | next to one another or nested) can combine to form a single margin. | Margins that behave this way are called <dfn>collapsing margins</dfn>. | | Two margins are adjoining if and only if: | * no non-empty content, padding or border areas; line boxes; | or clearance separate them | * both belong to normal-flow block-level boxes in the same block | formatting context This has several effects: - Gets rid of awkwardness in definition of "collapsing margins" - Shifts out definition of "adjoining" into a list that we can add to, as dbaron suggested at the end of http://lists.w3.org/Archives/Public/www-style/2010Feb/0015.html - Adds (2nd item) a simple rule that generalizes almost all of of the subsequent rules in the section. Replaced # In CSS 2.1, horizontal margins never collapse. # # Vertical margins may collapse between certain boxes: # * Two or more adjoining vertical margins of block boxes in # the normal flow collapse. with | Vertical margins collapse if they are adjoining. (Horizontal margins | never collapse.) in conjunction with the above definition of 'adjoining'. Pulled # The resulting margin width is # the maximum of the adjoining margin widths. In the case # of negative margins, the maximum of the absolute values # of the negative adjoining margins is deducted from the # maximum of the positive adjoining margins. If there are # no positive margins, the absolute maximum of the negative # adjoining margins is deducted from zero. out into its own paragraph about margin-collapsing math: | When two or more margins collapse, the resulting margin width is the | maximum of the adjoining margin widths. In the case of negative | margins, the maximum of the absolute values of the negative adjoining | margins is deducted from the maximum of the positive adjoining margins. | If there are no positive margins, the absolute maximum of the negative | adjoining margins is deducted from zero. which is placed after all the conditions for when margins collapse. Took # Note. Adjoining # boxes may be generated by elements that are not related # as siblings or ancestors. And tossed it higher, immediately after the definition of adjoining | Two margins are adjoining if and only if: | ... [3-item list here] ... | Note. Adjoining boxes may be generated by elements that are not | related as siblings or ancestors. The next four rules: # * Vertical margins between a floated box and any other box # do not collapse (not even between a float and its in-flow # children). # * Vertical 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. # * Margins of absolutely positioned boxes do not collapse # (not even with their in-flow children). # * Margins of inline-block elements do not collapse (not # even with their in-flow children). are special cases of | * both belong to normal-flow block-level boxes in the same block | formatting context so I shoved them into a new list: | Note the above rules imply that: | * Vertical margins between a floated box and any other box do not | collapse (not even between a float and its in-flow children). | * Vertical 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. | * Margins of absolutely positioned boxes do not collapse (not even | with their in-flow children). | * Margins of inline-block elements do not collapse (not even with | their in-flow children). The next rule is all about calculating the element's position: # * If the top and bottom margins of a box are adjoining, # then it is possible for margins to collapse through it. # In this case, the position of the element depends on its # relationship with the other elements whose margins are # being collapsed. # o If the element's margins are collapsed with its # parent's top margin, the top border edge of the # box is defined to be the same as the parent's. # o Otherwise, either the element's parent is not # taking part in the margin collapsing, or only the # parent's bottom margin is involved. The position # of the element's top border edge is the same as it # would have been if the element had a non-zero bottom # border. # ... [[ see below for this paragraph ]] ... # Note that the positions of elements that have been # collapsed through have no effect on the positions of the # other elements with whose margins they are being collapsed; # the top border edge position is only required for laying # out descendants of these elements. I pulled it out into its own set of paragraphs at the end of all the explanations of what margins collapse and how: | If the top and bottom margins of a box are adjoining, then it is | possible for margins to collapse through it. In this case, the | position of the element depends on its relationship with the other | elements whose margins are being collapsed. | * If the element's margins are collapsed with its parent's top | margin, the top border edge of the box is defined to be the | same as the parent's. | * Otherwise, either the element's parent is not taking part in | the margin collapsing, or only the parent's bottom margin is | involved. The position of the element's top border edge is | the same as it would have been if the element had a non-zero | bottom border. | Note that the positions of elements that have been collapsed through | have no effect on the positions of the other elements with whose | margins they are being collapsed; the top border edge position is | only required for laying out descendants of these elements. The paragraph I removed from the middle of that section # An element that has clearance never collapses its top # margin with its parent block's bottom margin. has very little to do with the rest of the section. I combined it with the other statement on the same topic that's further down # When an element's own margins collapse, and that element has # clearance, its top margin collapses with the adjoining margins # of subsequent siblings but that resulting margin does not # collapse with the bottom margin of the parent block. and took the combination, along with the next rule # * Margins of the root element's box do not collapse. and put them back up next to the statement of what margins collapse: | Vertical margins collapse if they are adjoining. (Horizontal margins | never collapse.) >>> However: | * Margins of the root element's box do not collapse. | * If the top and bottom margins of an element with clearance are | adjoining, its margins collapse with the adjoining margins of | subsequent siblings but that resulting margin does not collapse | with the bottom margin of the parent block. <<< The next three paragraphs after the list are merely illustrating the rules that define "adjoining": # The bottom margin of an in-flow block-level element is always # adjoining to the top margin of its next in-flow block-level # sibling, unless that sibling has clearance. # # The top margin of an in-flow block-level element is adjoining # to 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. # # The bottom margin of an in-flow block-level element with a # 'height' of 'auto' is adjoining to its last in-flow block-level # child's bottom margin if the element has no bottom padding or # border. # # An element's own margins are adjoining 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) are adjoining. So I replaced "is adjoining to" with "collapses with" for consistency and stuffed them into the "implications" list: | Note the above rules imply that: | ... | * 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. | * The top margin of an in-flow block-level 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. | * The bottom margin of an in-flow block-level element with a | 'height' of 'auto' collapses with its last in-flow block-level | child's bottom margin if the element has no bottom padding or | border. | * An element'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) are adjoining. (Note the conditions on the last two rules are implied particularly by the "no non-empty content area" and "no line boxes" requirements, if you're having trouble figuring out why it's "implied".) ~fantasai
Received on Thursday, 29 July 2010 03:01:48 UTC