This one surprises almost everyone. When the vertical margins of two blocks touch, they do not add. They merge, and the bigger one wins.
<style>
p { margin: 0; background: #d0e8f2; padding: 8px; }
.a { margin-bottom: 40px; }
.b { margin-top: 20px; }
</style>
<p class="a">Margin-bottom: 40px</p>
<p class="b">Margin-top: 20px</p>
You might expect 60px between the boxes. You get 40px: the larger of the two.
When does it happen?
- Between two siblings, as above.
- Between a parent and its first or last child, when nothing (no padding, no border) separates them. The child’s margin seems to escape and push the parent instead.
- On empty blocks, where top and bottom margin merge with each other.
It only applies to vertical margins
Left and right margins never collapse. And it does not happen for flex and grid items, or between floated or absolutely positioned boxes.
The simple ways around it
- Pick one direction. Only use
margin-bottomon blocks (or onlymargin-top). Then there are no two margins to collapse. - Use
gap. In flexbox and grid layouts,gapcreates space between items with no collapsing. See Flex Gap. - Add padding or a border to the parent so the child’s margin stays inside.
/* Consistent spacing: every block gets space below it */
.article > * + * { margin-top: 1rem; }
That last rule uses the sibling selector you saw earlier, CSS Sibling Selectors, to space out a column of content.