Collapsing Margins
Let’s explore exactly what the consequences of collapsing margins are, and how they will affect elements on the page.
The W3C specification defines collapsing margins as follows:
"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."
In simple terms, this definition indicates that when the vertical margins of two elements are touching, only the margin of the element with the largest margin value will be honored, while the margin of the element with the smaller margin value will be collapsed to zero.1 In the case where one element has a negative margin, the margin values are added together to determine the final value. If both are negative, the greater negative value is used. This definition applies to adjacent elements and nested elements.
There are other situations where elements do not have their margins collapsed:
- floated elements
- absolutely positioned elements
- inline-block elements
- elements with
overflowset to anything other thanvisible(They do not collapse margins with their children.) - cleared elements (They do not collapse their top margins with their parent block’s bottom margin.)
- the root element
This is a difficult concept to grasp, so let’s dive into some examples.
Collapsing Margins Between Adjacent Elements
Margins collapse between adjacent elements. In simple
terms, this means that for adjacent vertical block-level elements in the
normal document flow, only the margin of the element with the largest
margin value will be honored, while the margin of the element with the
smaller margin value will be collapsed to zero. If, for example, one
element has a 25px bottom margin and the element
immediately underneath it has a 20px top margin, only
the 25px bottom margin will be enforced, and the
elements will remain at a distance of 25px from each
other. They will not be 45px (25+20) apart, as might
be expected.
This behavior is best demonstrated with a short example. Consider the following code:
h1 {
margin: 0 0 25px 0;
background: #cfc;
}
p {
margin: 20px 0 0 0;
background: #cf9;
}
As you’ll see from Figure 1, the gap
between the elements is only 25px, and the smaller
margin has collapsed to zero. If in the above example the elements had
equal margins (say, 20 pixels each), the distance between them would be
only 20px.2
There is one situation that will cause a slight deviation from the behavior of collapsing margins: should one of the elements have a negative top or bottom margin, the positive and negative margins will be added together to reach the final, true margin. Here’s an example style sheet that demonstrates the concept:
h1 {
margin: 0 0 25px 0;
background: #cfc;
}
p {
margin: -20px 0 0 0;
background: #cf9;
}
The bottom margin of the h1 element is a
positive number (25px), and the top margin of the
p element is a negative number
(-20px). In this situation, the two numbers are added
together to calculate the final margin: 25px + (-20px) =
5px.
If the result of this calculation is a negative number, this value will have the effect of one element overlapping the other. You could say that the negative margin pulls the element in the opposite direction to that of a positive margin. See margin for more details about negative margins.
Collapsing Margins Between Parent and Child Elements
So far, we’ve only addressed the collapsing effect on adjacent elements, but the same process holds true for parents and children whose margins touch. By “touch,” we mean the places at which no padding, borders, or content exist between the adjacent margins. In the following example, a parent element has a child element on which a top margin is set:
h1 {
margin: 0;
background: #cff;
}
div {
margin: 40px 0 25px 0;
background: #cfc;
}
p {
margin: 20px 0 0 0;
background: #cf9;
}
In the style sheet above, you can see that a top margin value
is declared for the p element, and in the code excerpt
below, you can see that the p element is a child of the
div element:
<h1>Heading Content</h1> <div> <p>Paragraph content</p> </div>
The result of this code is illustrated in Figure 2.
You may have expected that the paragraph would be located
60px from the heading, since the
div element has a margin-top of
40px and there is a further 20px
margin-top on the p element. You may
also have expected that 20px of the background color
of the div element would show above the paragraph. This
does not happen because, as you can see in Figure 2, the
margins collapse together to form one margin. Only the largest margin
applies (as in the case of adjoining blocks), as we’ve already
seen.
In fact we would get the same result if our
div element had no top margin and the
p element had a 40px
margin-top. The 40px
margin-top on the p element
effectively becomes the top margin of the div element,
and pushes the div down the page by
40px, leaving the p element
nesting snugly at the top. No background would be visible on the
div element above the paragraph.
In order for the
top margins of both elements to be displayed, and for the background of
the div element to be revealed above the
p element, there would need to be a border or padding
that would stop the margins collapsing. If we simply add a top border to
the div element, we can achieve the effect we were
originally looking for:
h1 {
margin: 0;
background: #cff;
}
div {
margin: 40px 0 25px 0;
background: #cfc;
border-top: 1px solid #000;
}
p {
margin: 20px 0 0 0;
background: #cf9;
}
In Figure 3, we can
see that the div element is still
40px away from the heading, but the paragraph has
been pushed a further 20px down the page, thus
revealing 20px of the background of the
div element (through the presence of the
border).
If we didn’t want a visible top border showing in the design, a
1px top padding on the div element
would have achieved the same effect. Note that the border or padding
should be applied to the parent div because a border on
the paragraph would not stop the margins from collapsing, since the
paragraph’s margin is outside of the border.
As of this writing, Internet Explorer versions 7 and below will not
collapse margins where the element has a layout. If the
div in our example simply had a width set (one of
the triggers that causes an element to gain a layout), we’d get the
result shown in Figure 3,
without the need to add padding or borders.
This is non-standard behavior for IE, and is perhaps one of the
reasons why beginners are a little confused by the concept of
collapsing margins when they first come across it. Most of the time,
the elements will have a value (other than auto)
for the width property (or one of the other
properties that causes an element to gain a layout), and will not
exhibit the collapsing margin behavior in IE.
The example above deals with a single parent and single child that have touching margins, but the same approach would apply if there were several children (that is, nested elements) that all had adjacent vertical margins: it would still mean that all the margins would collapse into one single margin. Although the examples above mentioned top margins, the same effect is true for bottom margins, as can be seen below.
In the following contrived example, we’ve nested four
div elements, all of which have a
10px margin applied. Each div has
a different background color, so the effects of the margin collapse will
be clearly visible:
.box {
margin: 10px;
}
.a {
background: #777;
}
.b {
background: #999;
}
.c {
background: #bbb;
}
.d {
background: #ddd;
}
.e {
background: #fff;
}
<div class="box a">
<div class="box b">
<div class="box c">
<div class="box d">
<div class="box e">
The vertical margins collapse but the horizontal
margins don't. The vertical margins also collapse
in IE because the elements don't have a layout.
</div>
</div>
</div>
</div>
</div>
The result of the above CSS is shown in Figure 4.
As you can see in this example, the effect of our CSS is quite
dramatic: all the vertical margins have collapsed to form a single,
10px margin. Unlike the horizontal margin example,
where all the margins were visible, the vertical margins show no such
colors at all, thanks to the background-color that has
been applied to each element. The whole block will be positioned
10px from other in-flow elements on the page, but
each nested block will collapse its margins into a single margin.
As
discussed earlier, the simplest way to stop the margin collapse from
occurring is to add padding or borders to each element. If we wanted 10px
margins on each element we could simply use a 9px
margin and 1px of padding to get the result we
wanted:
.box {
margin: 9px;
padding: 1px;
}
The result of that small change will “un-collapse” the vertical margins, as you can see in Figure 5.
Again, it’s important to consider the effects that layout in
Internet Explorer would have in the above demonstrations. Should the
elements in the first example (Figure 4) have a
layout in IE, the result would be exactly as shown in Figure 5. It’s
also worth noting that in browsers other than IE, the same effect would
occur if the overflow property was added with a value
other than visible.
Wrapping It Up
Although the margin collapse behavior is at first a little unintuitive, it does make life easier in the case of multiple nested elements, where the behavior is often desirable. As shown above, easy methods are available to help you stop the collapse if required.
User-contributed notes
- ID:
- #7
- Date:
- Wed, 19 Mar 2008 21:28:12 GMT
- Status:
- This note has not yet been confirmed for accuracy and relevance.
in line with:
"As of this writing, Internet Explorer versions 7 and below will not collapse margins where the element has a layout. "
also an element with hasLayout containing an element with no explicit margin set i.e. using only default margins
e.g. floated element with a <p> inside it
IE will appear to wrongly collapse the margins of the <p>.. adding border or padding will not fix it so it's not actually collapsing margins it's just not counting them.
:adding explicit margins to the p will fix it.
Add a note
To post a note on this topic, please log in with your SitePoint username and password. If you don't have an account yet, you can create a new account for free.
