- 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