Bobby
Bobby

Reputation: 931

Inner div's margin affecting containing div's margin

I have an inner div inside a containing div.

HTML

<div id="container">
  <div id="inner"></div>
</div>

CSS

#container {
    width: 100px;
    height: 100px;
    background-color: red;
}
#inner {
    margin: 30px;
    width: 40px;
    height: 40px;
    background-color: black;
}

Fiddle

http://jsfiddle.net/8xUTJ/4/

I expect this to make a small black box centered vertically and horizontally in a bigger red box. Instead I get a black box stuck to the top of the red box, and the red box has the margin-top.

Can someone explain what CSS thinks it is doing here?

Upvotes: 21

Views: 6551

Answers (5)

Mr_Green
Mr_Green

Reputation: 41852

check this fiddle

You need to float the inner div to make it work

#inner {    
    margin:30px;
    float:left;   /* give float */
    width: 40px;
    height: 40px;
    background-color: black;
 }​

Or else give overflow:auto property to the div#container.

check this fiddle

Upvotes: 1

Oleg
Oleg

Reputation: 25008

First, #container has margin-top:0 and #inner has margin-top:30px. The relationship of these elements is that of a parent and a first child.

If there is no border, padding, inline content, or clearance to separate the margin-top of a block with the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block with the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent.

Margin collapsing means these margins are combined into a single margin whose size is the largest of the margins combined into it

These rules apply even to margins that are zero, so the margin of a first/last child ends up outside its parent (according to the rules above) whether or not the parent's margin is zero

This is why you end up with 30px top margin applied outside of the #container element, from your fiddle:

30px and 0 top margins collapse

Upvotes: 2

Ryan Wheale
Ryan Wheale

Reputation: 28450

While the solutions provided are viable, nobody explains the problem. It's called margin collapsing which happens in several scenarios.

Scenario 1 - these items will only be 30px apart, because the margins collapse together and the larger one prevails.

<div style="margin-bottom: 20px"></div>
<div style="margin-top: 30px"></div>

Scenario 2 - (your scenario) the margin of the inner box spills outside of the outer box.

<div class="outer">
    <div style="margin-top: 20px"></div>
</div>

The solution is to give the outer box some padding or a border (as suggested by others). Often times, I use the following CSS on the outer box to mitigate situations like this:

.outer {
    margin-top: -1px;
    border-top: 1px solid transparent;
}

Upvotes: 15

j08691
j08691

Reputation: 208032

Add overflow:auto to the #container div.

jsFiddle example

Or

add a border to the #container div.

You can read more about this collapsing margin behavior at the W3C.

Upvotes: 30

d-_-b
d-_-b

Reputation: 23211

method 1

position:absolute for the inner div, so it knows what to be 30px margin from

http://jsfiddle.net/8xUTJ/5/


method 2

display:inline-block for the inner div

http://jsfiddle.net/8xUTJ/7/


method 3

border:solid 0 transparent to outer div

http://jsfiddle.net/8xUTJ/8/

Take your pick :)

Upvotes: 3

Related Questions