Search code examples
csscss-gridmargin

Does CSS grid suppress margin collapse inside grid items?


I understand that a CSS grid element suppresses margin collapse between child grid items that are adjacent (adjacent siblings).

But what I think I'm seeing is that a grid element also seems to suppress margin collapse within a single grid item, by suppressing margin collapse between that item and that item's own children (parent-descendant margin collapse).

Is that what's going on? Is that what's supposed to happen?

You can see it in a snippet like this:

main {  
  display: grid; 
  outline: 1px solid green;
}

section {
  margin: 25px 0 25px 0;
  outline: 1px solid red;
}

div {
  margin: 25px 0 25px 0;
  outline: 1px solid blue;
}
<main>
  <section>
    <div>X</div>
    <div>Y</div>
  </section>
</main>

As you can see if you run this snippet, there is 25 px of space between X and Y. This is because the X's 25px margin-bottom is collapsing with its adjacent sibling Y's 25px margin-top, as expected.

But there is 50 px of space between the X content area (outlined in blue) and the top of the grid item content area (outlined in green). This seems to be because the X div's 25px margin-top is adding and not collapsing with the section's 25px margin-top. This is what I find confusing.

If you switch main to display:block, then you get the normal collapse behavior, where the margin-top of div and of section collapse together. They also collapse with the margin-top of main itself, so that marginal space extends outside main's content area (outlined in green).

I don't understand why this is happening and can't see what in the spec would imply that a grid should affect collapse behavior within a grid item.


Solution

  • From the specificaton:

    A grid item establishes an independent formatting context for its contents. However, grid items are grid-level boxes, not block-level boxes: they participate in their container’s grid formatting context, not in a block formatting context.

    and

    Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.ref

    So margin inside a grid item cannot collapse with the margin of the grid item that are outside

    You can have margin collapsing inside the grid if all the concerned margin are inside

    main {
      display: grid;
    }
    
    section {
      margin: 25px 0;
      outline: 1px solid red;
    }
    
    div {
      margin: 25px 0;
      outline: 1px solid blue;
    }
    <main>
      <section>
        <div>X</div>
        <div>X</div>
      </section>
    </main>

    As you can see, we only have 25px between the two divs inside the grid item