Set a bottom margin on one paragraph and a top margin on the next, and the gap between them is not the sum of the two. It is the larger of them. This behaviour has a name — collapsing margins — and it is the reason a gap you expected to be forty pixels is twenty.
What collapses, and what does not?
Vertical margins between block-level elements collapse. The space between them becomes the larger of the two margins, not their sum, and it is called a collapsed margin.
.first { margin-bottom: 30px; }
.second { margin-top: 20px; }
/* the gap between them is 30px, not 50px */
Three situations are involved. Two adjacent siblings with no border, padding or clearance between them collapse. A parent's top margin collapses with its first child's top margin when there is nothing separating them. And a parent's bottom margin collapses with its last child's bottom margin for the same reason.
<div class="parent">
<p class="first">First paragraph</p>
</div>
<div class="next">Next block</div>
.parent { margin-bottom: 40px; }
.first { margin-top: 20px; }
Here the child's 20 pixels of top margin collapses out through the parent, and the gap between the two blocks is 40 pixels, not 60. The child appears to have moved up out of its parent, and the parent's background does not extend to cover that space.
What prevents collapsing?
Anything that separates the margins vertically. A border, a padding, or a clearance on the parent stops the parent's margin from collapsing with its children's. A flex or grid container stops collapsing between its children entirely.
/* padding on the parent keeps the child's margin inside */
.parent { padding: 1px; }
/* or a flex container: no collapsing between flex items */
.parent { display: flex; flex-direction: column; }
/* or overflow other than visible */
.parent { overflow: auto; }
Flex and grid are the modern answer, because they solve the problem structurally: in a flex column, the space between two items is their margins added together, exactly as you would expect. This is one of the practical reasons people use flexbox for vertical stacks instead of plain block layout.
Why does it work this way at all?
Because the model is built around the idea of a single gap between two boxes. If every pair of margins added up, a stack of paragraphs with a 20-pixel top and bottom margin each would have 40 pixels between every pair, and the space at the top and bottom of the document would be missing. Collapsing gives one consistent gap and removes the outer gaps, which is why the first element's top margin often appears to move the whole page down instead of appearing above the text.
The behaviour has a second effect that surprises people: a block with a margin-top larger than the viewport height will push the page down, and the space above it cannot be scrolled to. That is the "margin at the top of the page" problem, and the fix is to put the spacing on the parent instead.
/* instead of a top margin on the first element */
h1 { margin-top: 2rem; }
/* put the space on the container */
.page { padding-top: 2rem; }
How do I work out where a gap came from?
Turn on the box model overlay and hover the elements. The overlay draws the margin areas, and when two margin areas overlap you can see the collapse happening: the two translucent bands sit on top of each other rather than stacking.
sibling margins
30px └──┐
├── one collapsed gap of 30px
20px ┌──┘
parent and child
40px └──┐
20px ┌──┘ the child's margin has escaped the parent
Three fixes cover nearly every case. Use flex or grid for the container, which removes collapsing between items. Add a small padding or border to the parent when you need a child's margin to stay inside it. Or use the gap property in a flex or grid container, which is explicit about the space and never collapses.
/* the clearest way to space a stack */
.stack {
display: flex;
flex-direction: column;
gap: 1rem;
}
How do you use collapsing margins deliberately?
Collapsing is usually something you fight, but it is also a feature you can lean on. Because two adjoining vertical margins collapse into one, a stack of elements with margin-bottom: 1rem each will be separated by exactly 1rem, not 2rem. That gives you even rhythm without a wrapper element or a gap property to maintain.
<section class="article">
<h2>Heading</h2>
<p>First paragraph.</p>
<p>Second paragraph.</p>
</section>.article h2 {
margin-block: 0 0.5rem;
}
.article p {
margin-block: 0 1rem;
}
/* the gap between two paragraphs is 1rem, not 2rem */
.article p + p {
margin-block-start: 1rem;
}The collapsing rule only applies to adjoining margins - that is, margins with no padding, border, content or clearance between them. Margins on the same element always add up, and margins separated by anything else stay separate. So the collapse happens between the bottom margin of one paragraph and the top margin of the next, and never between two margins of the same element.
Two things prevent a collapse, and both of them are useful to know on purpose. A parent with no padding, border, height or content of its own lets its first child's top margin and its last child's bottom margin escape out through it, so the parent ends up in the wrong place. Adding overflow: hidden, a border, or display: flow-root on the parent stops the escape - and flow-root is the cleanest of the three, because it says exactly what it means: make this element a block formatting context.
Quick reference
- Adjacent vertical margins collapse: the gap is the larger of the two, not the sum.
- A parent's margin can collapse with its first and last child's.
- Padding, a border, or a flex or grid container stops the collapsing.
- In flex and grid, margins add normally, and
gapis usually clearer. - A top margin on the first element moves the page down instead of adding space above it — pad the container instead.
Try it yourself: put two paragraphs in a column with a 30-pixel bottom margin on the first and a 20-pixel top margin on the second. Measure the gap. Then change the container to display: flex; flex-direction: column and measure again — the gap should now be 50 pixels, because flex items do not collapse.