htmlcssmargin

Why is margin collapsing between parent and child even when `overflow: hidden` is used (BFC)?


I'm trying to understand how margin collapsing behaves when a Block Formatting Context (BFC) is introduced using overflow: hidden.

Here is a minimal reproducible example:

.outer {
  background: lightblue;
}

.inner {
  background: lightgreen;
  overflow: hidden; /* Triggers BFC */
  margin: 30px;
}

p {
  margin-top: 30px;
}
<body>
  <div class="outer">
    <div class="inner">
      <p>Paragraph inside a BFC.</p>
    </div>
  </div>
</body>

From my understanding, setting overflow: hidden on .inner should create a Block Formatting Context, which prevents margin collapsing between .inner and its parent .outer.

However, when I inspect the layout in Chrome DevTools, it appears that the top margin of .inner is still collapsing upward, making it look like .outer has a top margin — even though it doesn’t.

Outer wrapper has no margin

Inner wrapper's margin "bleeds" outside the Outer area

Paragraph's block-margin affects height of the Outer wrapper

Question:
Why does margin collapsing still occur here even though .inner should be a BFC? Is there something I’m missing?


Solution

  • BFC works strictly "inwards", so the ("outer") margin of an element that constitutes BFC will still "bleed" (collapse), unless its parent is also BFC.

    BFC will only make margins of inside child elements push the BFC's element's boundary, preventing the regular margin-block collapse.

    It is nicely visible in your sample, where the BFC is only the .inner wrapper: the innermost paragraph's margin makes that .inner parent stretch. If the .inner did NOT have the overflow: hidden in your test, it would shrink and let paragraphs margin bleed/collapse into its own, and outside the .outer, and effectively shrink everything to:

    Narrow paragraph

    And similarly, if you add extra overflow: hidden to the .outer, and keep it on the .inner as well, you'll get what you probably initially expected:

    Super tall .outer