Margin Collapse in CSS

Hero image for Margin Collapse in CSS. Image by William Warby.
Hero image for '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 boxmodel 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 on the CodePen below.

https://codepen.io/johnkavanagh/pen/YzNeOEy

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 inlineblock 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...

https://codepen.io/johnkavanagh/pen/qBRxMoW

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. When both a child and parent have margins applied in the same direction, they collapse. Take a look the pen below for a clearer visual:

https://codepen.io/johnkavanagh/pen/ZELrMmV

Are you seeing that? The child has a marginbottom of 24px, and the parent has a marginbottom 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 marginbottom from the parent element, while we're at it. What would you expect to happen? Check out the results below.

https://codepen.io/johnkavanagh/pen/dyNdqLM

That's right. The margin on the child element pushes the sibling of the parent element. Margins have no respect for boundaries, and because of the way parent and child margins collapse, they transfer up the DOM tree from child to parent elements. It's frustrating, and not a particularly uncommon issue and it's definitely something that would leave you scratching your head a little.


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.


Categories:

  1. CSS
  2. Development
  3. Front‑End Development
  4. Guides