What is margin collapsing, when does it happen, and how do you prevent it?

Intermediate12 min interview
Skills tested:
Naming the three collapsing cases: adjacent siblings, parent-first child, empty blockPredicting the resulting gap when two margins collapse, including negative valuesExplaining why a parent with no padding or border leaks its child marginListing the mechanisms that block collapsing and their side effectsKnowing that flex, grid, and absolutely positioned boxes are immune

Advertisement

🧩 Scenario

Margin collapsing is the reason a card with margin-top: 32px on its heading sometimes pushes the whole card down the page instead of pushing the heading down inside it. It is also why two stacked sections separated by 40px and 40px are 40px apart rather than 80px. The behaviour is intentional and mostly helpful for prose, but it is unpredictable to anyone who has not learned the three cases, and it produces bugs that look like the wrong element is misbehaving.

Architecture Walkthrough

The Three Cases

Margin collapsing means two or more margins in the block direction combine into a single margin instead of adding. It happens in exactly three situations, all confined to block-level boxes in normal flow.

Adjacent siblings. The bottom margin of one block and the top margin of the next block collapse into one. Two paragraphs with margin-bottom: 20px and margin-top: 30px sit 30px apart, not 50px.

Parent and first or last child. If nothing separates a parent's top edge from its first child's top margin, the two collapse and the margin appears outside the parent. The same applies at the bottom with the last child. "Nothing separates them" means the parent has no top border, no top padding, no inline content before the child, and no block formatting context of its own.

Empty blocks. A block with no content, no padding, no border, and no height collapses its own top and bottom margins into a single margin. margin: 20px 0 on an empty div produces 20px of total space, not 40px.

The Resulting Value Is Not Always the Larger One

The common shorthand is "the larger margin wins," which is only true when both are positive. The real rule handles negatives too.

If both margins are positive, the result is the larger. If both are negative, the result is the more negative one, meaning the larger absolute value. If one is positive and one is negative, they are summed. So margin-bottom: 30px next to margin-top: -10px yields a 20px gap, and -20px next to -5px yields -20px.

Why Parent-Child Collapsing Feels Like a Bug

The sibling case is intuitive enough that most developers absorb it without ever naming it. The parent-child case is the one that generates support tickets, because the symptom points at the wrong element.

Consider a card with a background colour and a heading inside it carrying margin-top: 32px. If the card has no top padding or border, that 32px collapses out through the card's top edge. The visible result is the entire card pushed 32px down the page, with the heading flush against the card's top edge and the background not extending into the space at all. Nothing about the card's own CSS explains what you see; the space is coming from its child.

Preventing It

Anything that separates the parent's edge from the child's margin blocks the collapse, and anything that establishes a new block formatting context blocks it as well.

Adding padding-top or border-top to the parent, even a fraction of a pixel, is the cheapest fix and usually the one the design actually wanted. Establishing a block formatting context works too: overflow: hidden or overflow: auto, display: flow-root, display: flex, display: grid, absolute or fixed positioning, and floating all do it. display: flow-root is the purpose-built keyword for this: it creates the formatting context and nothing else, with no clipping and no layout change.

The historically popular overflow: hidden fix is the one to be careful with, because it clips anything that overflows the parent. Box shadows, focus rings, tooltips, and dropdown menus that need to escape the container all get cut off, and the connection between "I fixed a margin problem" and "my dropdown is now truncated" is not obvious weeks later.

Finally, the structural fix: flex and grid items never collapse margins, with each other or with their container. Absolutely and fixed positioned boxes do not collapse either. In practice, laying out a stack with display: flex; flex-direction: column; gap: 24px sidesteps the entire topic, which is why margin collapsing shows up far less in modern codebases than it did in float-based ones.


Key Code Explained

/* Case 1: adjacent siblings -> gap is 30px, not 50px */
.para-a {
  margin-bottom: 20px;
}
.para-b {
  margin-top: 30px;
}

/* Mixed signs are SUMMED, not "larger wins" -> gap is 20px */
.mixed-a {
  margin-bottom: 30px;
}
.mixed-b {
  margin-top: -10px;
}

/* Case 2: parent-child. The child margin escapes the parent. */
.card {
  background: #fff;
  /* no padding-top, no border-top, no formatting context */
}
.card > h2 {
  margin-top: 32px; /* pushes the whole .card down, not the h2 inside it */
}

/* Fix A: separate the edges (usually what the design wanted anyway) */
.card-padded {
  background: #fff;
  padding-top: 1px; /* or any real padding / border-top */
}

/* Fix B: new block formatting context, no side effects */
.card-bfc {
  background: #fff;
  display: flow-root; /* purpose-built: contains margins, clips nothing */
}

/* Fix C: overflow — works, but CLIPS shadows, tooltips, dropdowns */
.card-overflow {
  background: #fff;
  overflow: hidden;
}

/* Case 3: empty block collapses its own margins -> 20px total, not 40px */
.spacer {
  margin: 20px 0;
  /* no content, no height, no padding, no border */
}

/* Structural fix: flex and grid items never collapse */
.stack {
  display: flex;
  flex-direction: column;
  gap: 24px; /* predictable, never collapses, no last-child override */
}

The .card and .card > h2 pair is the example to be able to reproduce on demand. It is the clearest demonstration that collapsing makes the symptom appear on a different element from the cause: the heading's margin visibly moves the card, and reading the card's own rules gives you no hint why.

The contrast between display: flow-root and overflow: hidden is the other detail worth carrying into an interview. Both fix the collapse by establishing a block formatting context, but only one of them also silently clips your box shadows.


Tradeoffs

Prevention techniqueBlocks collapsingSide effects
padding-top / border-top on parentYes, top edge onlyChanges visual spacing, adds a visible border
display: flow-rootYes, both edgesNone; purpose-built for this
overflow: hidden / autoYes, both edgesClips shadows, tooltips, dropdowns; auto may add scrollbars
display: flex / gridYes, and between children tooChanges the layout model entirely
Absolute / fixed positioningYesRemoves the box from normal flow
Use gap instead of marginsN/A, nothing to collapseRequires a flex or grid parent

What Interviewers Actually Check

  • Whether you can name all three collapsing cases rather than only the sibling one
  • Whether you know the resulting value rule for negative and mixed-sign margins, not just "larger wins"
  • Whether you can diagnose the parent-child case from the symptom, where the wrong element appears to move
  • Whether you know more than one prevention technique and can state the cost of each
  • Whether you know flex and grid items are immune, and can explain why that makes the problem rarer today

Follow-Up Questions

  1. What exactly is a block formatting context, and why does creating one stop margins from collapsing through a parent?
  2. Why did the CSS working group specify collapsing at all, and what would document flow look like without it?
  3. What does the margin-trim property propose, and how would it change the :last-child { margin-bottom: 0 } pattern?
  4. Do margins collapse through an element that has height: 0 but a 1px border? Why or why not?
  5. In a vertical writing mode, which margins collapse, and does the answer change from horizontal writing modes?

Common Candidate Mistakes

  • Adding two adjacent margins together, then treating the smaller-than-expected gap as a browser bug rather than specified collapsing behaviour
  • Debugging a card that is offset down the page by inspecting the card's own rules, when the offset comes from the first child's margin-top escaping through the top edge
  • Reaching for overflow: hidden as the reflexive fix and later discovering clipped box shadows, focus rings, or a dropdown that cannot escape the container, when display: flow-root would have done the job cleanly
  • Assuming horizontal margins collapse as well, when only block-direction margins ever do
  • Assuming flex or grid items collapse with each other or with their container, when neither ever happens and gap is the intended spacing tool there

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you name all three collapsing cases and give a concrete example of each?
  • Can you compute the collapsed result when one margin is negative and when both are?
  • Can you explain the parent-child case and why the symptom appears on the parent rather than the child?
  • Can you list at least four ways to prevent collapsing and state the cost of each?
  • Can you explain why flex and grid layouts avoid the problem entirely?

Summary

Margin collapsing combines block-direction margins into a single margin instead of adding them, and it happens in three situations: between adjacent siblings, between a parent and its first or last child when nothing separates their edges, and within an empty block that collapses its own top and bottom margins. Horizontal margins never collapse.

The resulting value is the larger margin only when both are positive. If both are negative, the more negative one wins; if the signs are mixed, the two are summed. So a 30px bottom margin adjacent to a -10px top margin yields a 20px gap.

Prevention comes down to separating the edges or establishing a block formatting context. Adding top padding or a top border to the parent is the cheapest fix. display: flow-root is the purpose-built one, creating the formatting context with no clipping and no layout change, which makes it strictly better than the traditional overflow: hidden trick that silently clips shadows and dropdowns. Structurally, flex and grid items never collapse margins at all, so a column flex container with gap avoids the entire class of problem, which is why the behaviour surfaces far less often in modern layouts than it did in float-based ones.

Frequently Asked Questions

Do horizontal margins ever collapse?

No. Only margins in the block direction collapse, which is vertical in a standard horizontal writing mode. Left and right margins always add.

Does flexbox collapse margins?

No. Flex and grid items never collapse margins with each other or with their container, which is one reason modern layouts hit this problem far less often.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement