55

When an element with a margin is contained within another element, the parent does not consistently wrap/contain that margin.

Many things will cause the parent to contain the child's margin:

  • border: solid;
  • position: absolute;
  • display: inline-block;
  • overflow: auto;

(And this is just from a little testing, no doubt there are more.)

I would assume this has to do with collapsing margins, but:

  1. The W3C spec page has no description of such behavior.
  2. There are no overlapping margins here.
  3. Behavior of all browsers seems to be consistent on this issue.
  4. The behavior is affected by triggers that are not related to the margins.

What is the logic by which an element which defaults to overflow: auto should contain different material than the one where the overflow is set to auto?

Why should everything but the default behavior of a regular div assume that the margin is contained by the parent – and why should the regular default not include the margin?


EDIT: The final answer is that the W3C really does specify this behavior, but that:

  • The specs do not really make any sense.
  • The specs mix, without any word of explanation:
    • 'free margins' (margins that would touch the top or bottom of their parent are not contained by the parent) and
    • 'collapsed margins' (adjacent margins are allowed to overlap).

Demo:

body {
  margin: 0;
}

div.block {
  background-color: skyblue;
}
div.inline-block {
  display: inline-block;
  background-color: lawngreen;
}
div.position-absolute {
  background-color: rgba(255,255,0,.7);
  position: absolute;
  bottom: 0;
  right: 0;
}
div.overflow-auto {
  background-color: hotpink;
  overflow: auto;
}
div.border {
  background-color: aquamarine;
  border: solid;
}

h2 {
  margin: 80px;
  width: 250px;
  border: solid;
}
<div class="block">
  <h2>Is the margin contained (block)?</h2>
</div>
<div class="inline-block">
  <h2>Is the margin contained (inline-block)?</h2>
</div>
<div class="position-absolute">
  <h2>Is the margin contained (position-absolute)?</h2>
</div>
<div class="overflow-auto">
  <h2>Is the margin contained (overflow-auto)?</h2>
</div>
<div class="border">
  <h2>Is the margin contained (border)?</h2>
</div>

1
  • I dont understand what you are asking. Are you asking why the h1 elements display inside the container elements? Please be clearer with your question. Commented Feb 1, 2010 at 12:28

1 Answer 1

32

This is how CSS works according to W3C:

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.

More specific to your case of the top div:

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.

The best thing I can do is point you to on "Collapsing Margins" on sitepoint (by Tommy Olsson and Paul O’Brien). They do a very detailed explanation with examples showing you exactly the behaviors you demoed in the question example code.

3
  • According to that article, the behavior seen is incorrect. <br>Regarding your answer: "collapsing margins means that adjoining margins...combine". Since there are no adjoining margins here, this cannot be a collapsing margin. Specifically, "If the element's margins are collapsed with its parent's top margin" - cannot be, as the parent has no top margin. In the question I deal with collapsing margins. In either case, though, this would not explain why the behavior should change when the display is inline-block, or overflow is set to auto (which is the same as the default).
    – SamGoody
    Commented Feb 1, 2010 at 19:30
  • Correction: In that article it lists some of my triggers + others. Just as these triggers prevent overlapping margins from collapse, they prevent regular margins from collapse as well. Two questions: 1) How can this behavior make any sense? 2) Why does it think I have an overlapped margin?
    – SamGoody
    Commented Feb 1, 2010 at 19:42
  • 2
    @samgoody - 1) I agree it doesn't make much sense, except if you come from a print background, which is mostly what the web was when the spec was written. See here for that view: complexspiral.com/publications/uncollapsing-margins 2) It's a parent/child thing in your case...the collapse from the parent/child is giving div.b the 100px vertical margin, which is why that background white instead of green. I think the problem is the spec is unclear about WHICH margin wins in a collapse in this case, seems with current browser, the parent gets it. Commented Feb 1, 2010 at 22:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.