Margin Collapse in CSS

Image by William Warby.

CSS has a lot of quirks. Even common properties, like zindex, come with unexpected caveats that can easily catch developers out, and even leave experienced developers scratching their heads from time to time.

One of the more surprising properties that comes with jank included is the margin declaration.


Deceptively Simple

It's easy to think that margin should be pretty straightforward: it's literally just the amount of space on any side of the element, right? In fact, it should probably be the most simple part of the Box Model, given that we know padding can act differently depending on the box-model property and that border has a few different configurations too.

Except, like many things when it comes to something as simple as CSS, it is not. When interacting with other elements, and specifically other margins, the margin property reacts in some interesting, frustrating and downright strange ways.

Starting Simply...

This is the clearest and easiesttounderstand example of margin collapse, and it's probably the one you'll run into the most in the wild.

You've got two elements paragraphs, normally stacked in a column. When you stick a margin on the top and bottom of those elements, the margins above and below each element collapse, overlapping one another.

For instance, you've got 24px of margin on the bottom and the top of each paragraph element. The gap between each of those paragraph elements should be 48px, right? Wrong! Margins collapse into each other when they interact (sometimes, not all the time; we'll get into that in just a little bit), and the biggest margin wins.

This means that the gap between elements will only be as big as the biggest margin that separates them. When they're both equal, the gap is just equal to a single one of those margins. The gap between the paragraphs, in this case, is only 24px you can check this out in this CodePen.

Weird but not too janky, right? Let's keep going.

Margins Don't Collapse Horizontally.

Here's the first example of what I said earlier about margins only collapsing into each other sometimes. The above example only applies to vertical margins; for some reason, the creators of CSS decided against collapse happening horizontally.

In the below CodePen, you can see that we've now got two containing divs, aligned sidebyside by giving them the inline-block property. I've given them both margins on the left and right, with a value of 24px each.

The gap between them is 48px in total because these horizontal margins do not collapse. See this CodePen for proof.

Further down the rabbit hole we go...


Down the Rabbit Hole: Margins and Parent Elements

When elements are simply siblings, things are somewhat simple to remember. Only vertical collapse and the biggest margin swallows the smaller one whole. Not too tricky.

When parent elements are brought into the mix though, things get weird, surprising, and unexpected.

Parent and Child Collapse

This is one of the more unintuitive aspects of margin collapse. Parent and child vertical margins can collapse when they participate in the same block formatting context and nothing separates the relevant edges. A border or padding on that edge prevents collapse, as do flex and grid layout and a new block formatting context such as display: flowroot. Take a look at this pen for a clearer visual.Take a look at this pen for a clearer visual.

Are you seeing that? In this example, the parent has an automatic height, no minimum height and no bottom border or padding, whilst the inflow child is the last relevant descendant. Under those conditions, the child's 24px bottom margin can collapse with the parent's 24px bottom margin, leaving a 24px gap before the parent's sibling. Adding bottom padding or a border to the parent provides a contrasting case in which those margins no longer collapse.margin-bottom of 24px, and the parent has a margin-bottom of 24px, too. The child margin collapses into the parent margin, resulting in a gap between the parent and its sibling of 24px, with no evidence of the margin on the child element at all. You'd maybe expect that the bottom margin on the child would push it up in the container, away from the bottom of the parent but it just gets swallowed.

It's worth noting that in this instance, the vertical margin collapse only rule still applies. If you do this with margins on the left or right, you'll see it looking exactly how you'd expect.

But just hang on a minute because it's about to get even more counterintuitive.

Margin Transference

Let's take the example from above, with the parent and the child, and bump up the numbers for the child element. Let's take it from having a bottom margin of 24px, and give it a bottom margin of 48px instead. Let's remove the margin-bottom from the parent element, whilst we're at it. What would you expect to happen? Check out the results in my pen here.

Under the same collapsing conditions, the child's 48px bottom margin participates in the collapsed margin at the parent's outer edge, so the following sibling is separated by 48px. The margin has not travelled arbitrarily through the DOM: change the formatting context, take the child out of normal flow, or add a separating border or padding, and this result changes.


The Wrap‑Up

Margins seem straightforward and simple: all they do is add a predefined amount of space around the outside of your element. However, they can create situations that leave developers frustrated and confused due to a few fairly obscure and unusual quirks that have been part of the syntax since it was first introduced. Margin collapse is an unusual and janky hangover from when margins weren't intended to be used to control complex layouts, but it's fairly easy to get your head around once you know where the pitfalls are.


Need a senior engineer involved?

I can work directly in the codebase, review the architecture, or support the team through delivery when the work needs more than extra hands.