Mark McCann

Back

 •  Tutorial: CSS

Understanding Margin Collapse

There are two quirky scenarios where CSS margins do not behave the way you would expect them to. Being aware of them will go a long way to helping you avoid a big and unnecessary headache.

Sibling Rivalry

The first problem occurs when sibling elements have vertical margins facing one another.

The Example

<div class="upper">
    ...
</div>
<div class="lower">
    ...
</div>
.upper {
    margin-bottom: 30px;
}
.upper {
    margin-top: 50px;
}

In this case, you'd probably expect that margins to combine resulting in 80px of space between them, but unfortunately you'd be wrong.

Facing Vertical Margins Added Together
30px + 50px = 80px

The smaller margin gets consumed by the larger. So rude, right? The space between them ends up being 50px, not 80px.

Facing Vertical Margins Collapsed
30px + 50px = 50px

The same rule applies when both margins are negative; the greater margin absorbs the lesser.

(-30px) + (-50px) = -50px

When both margins are the same. One is used, while the other is absorbed.

30px + 30px = 30px

When one is negative and the other is positive; the negative margin is taken from the positive.

(-30px) + 50px = 20px

The Solution

How do you fix it? Short answer, you don't. The only way to "fix" this problem is to avoid it. I recommend applying margins (for vertical spacing) exclusively to the top or the bottom of your containers (I prefer the bottom). This way, you will never have margins meeting and risking a collapse. Life is so much easier when siblings aren't fighting.

Child Abuse

This next problem occurs when the margin of a child meets the margin of its parent.

The Example

<div class="parent">
    <div class="child">
        ...
    </div>
</div>

.parent {
    margin: 15px 0;
}
.child {
    margin: 10px 0;
}

In this case, you would probably think that the total margin would be the sum of both the parent and the child's margins, and again, you'd be wrong.

Parent and Child Margins Added Together
15px + 10px = 25px

The margin of the parent always overrules the margin of the child. This is the case even if the parent's margin is smaller than the child's. Pretty, harsh discipline if you ask me.

Parent and Child Margins Collapsed
15px + 10px = 15px

The Solution

There is a very simple remedy to this problem; As long as there is a "solid" object between the two competing margins, they will both be applied. Simply add an element, a border or even just 1px of padding and the child's margin will remain.

Parent and Child Margins Fixed
.parent {
    padding: 1px 0;
}

Another great solution is to add a pseudo element to the top and bottom of the container via CSS. Nicolas Gallagher combined this approach with the solution for fixing floats. So, the next time you run into either issue, all you have to do is add a class to the parent and you are good to go!

.clearfix:before,
.clearfix:after {
    content: '';
    display: table;
}
.clearfix:after {
    clear: both;
}

Other Resources

Here is another great guide on this topic from CSS Tricks.

Top