Margin Collapse in CSS

Abstract image used to represent 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 straightforward: just the space on each side of an element. It might seem like the simplest part of the box model, given that box-sizing changes how padding and borders contribute to a declared width or height.

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, suppose each paragraph has 24px of top and bottom margin. We might expect a 48px gap. When those vertical margins collapse, though, two positive margins combine into the larger one, leaving 24px here.

That 'larger margin wins' rule describes positive collapsing margins. With negative margins, the result combines the largest positive value with the most negative one; if they are all negative, the most negative value wins. Our positivemargin example leaves a 24px gap, as this CodePen shows.

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

For these adjacent siblings in normal block layout, collapsing positive vertical margins leave the larger margin. That gives us a useful starting point before looking at parents and children.

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

Parent and Child 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: flow-root. 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.

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.


Want to find out more?

If you need senior handson support with a complex React or Next.js platform, migration, performance issue, or technical SEO problem, send me the context and I'll tell you where I can help.