4

Let's say I have this small HTML snippet:

<div id="outer">
    <div id="inner">
        <div id="inner2">foo bar</div>
    </div>
</div>

I also have these styles defined:

#outer {
    height:100px;
    overflow:auto;
    background-color:#EEE;
}
#inner {
    height:100px;
    background-color:#AAA;
}
#inner2 {
    margin-top:5px;
}

With this setup, scroll bars appears with the outer div:

sample result

Why does the nested inner div causes this scrollbar to appears?

I can remove the scrollbar by removing the margin-top rule, but this would cause side effects.

Here is a jsfiddle that reproduces the issue: http://jsfiddle.net/stevebeauge/PTA85/

[edit]: my actual issue is solved by replacing margin-top by padding-top, but I'm looking for an explanation, not only the solution.

Steve B
  • 36,818
  • 21
  • 101
  • 174

1 Answers1

8

This is occurring because the margins are collapsing.

Box Model 8.3.1 Collapsing margins

In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

When two or more margins collapse, the resulting margin width is the maximum of the collapsing margins' 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 maximum of the absolute values of the adjoining margins is deducted from zero.

Possible workarounds:

Replace the margin with padding (example).

Add overflow:auto to #inner (example)

Float #inner2 (example)

Change the display of #inner2 from block to inline-block (example)

For additional information see The visual formatting model - Block formatting contexts.

Community
  • 1
  • 1
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • But there are no two sets of margins? how can they collapse if there is only one margin? The real reason is because of the `overflow:auto`. The innermost div is 100px tall + 2px margin top – Joseph Marikle Mar 20 '14 at 16:32
  • 1
    @JosephMarikle The element with margin has no height, and the one with `height:100px` has no margin. Then they shouldn't sum 100+2, but they do because of margin collapse. – Oriol Mar 20 '14 at 16:35
  • I see. For some reason I thought a height had been set on the innermost div. So then the parent containers collapse to an effective margin of -2px. is that correct? EDIT: no that doesn't make sense ether because there would then be a gap at the bottom. I'll do some research on this a bit. I clearly don't understand how overflow affects margin. – Joseph Marikle Mar 20 '14 at 16:39
  • @JosephMarikle It establishes a new block formatting context - http://www.w3.org/TR/CSS2/visuren.html#block-formatting – Josh Crozier Mar 20 '14 at 16:46
  • 1
    @JoshCrozier Fascinating. Thank you for the great subject to research! That last part about the block formatting context makes perfect sense and it leads me to believe I have been underutilizing the overflow property. – Joseph Marikle Mar 20 '14 at 16:56
  • 1
    Thanks @JoshCrozier. I'll follow the 1st workaround (replacing with padding), because I have no access to the code that generates the outer and inner divs (a long story related to obscure SharePoint html generation). Anyways, thanks for providing these solutions, and link to the explanation. – Steve B Mar 20 '14 at 19:49