Search code examples
htmlcsscss-grid

Odd behavior with grid, border, and anchor styling


I consider myself to be a fairly experienced CSS user, but this problem has stumped me. I have a basic CSS setup that I would expect to work in a predictable way.

.grid {
  display: grid;
}

.card > div {
  border-left: 1px solid black;
  height: 100%
}
<div class="grid">
  <a class="card" href="https://example.com">
    <div>
      <p>
        Hello Stackoverflow! There is 2em of margin below me!
      </p>
    </div>
  </a>
</div>

Note the interesting behavior where the bottom margin of the p appears to be 2em instead of the following reasonable expectations

  • 1em on top, 1em on bottom
  • 0em

This caught me off guard, so I messed with the values a bit. This is where it gets really interesting

  • remove display: grid: 2em on bottom drops to 0
  • remove height: 100%: 2em on the bottom drops to 0
  • change border-left to border: 1em on top, 1em on bottom

When we remove the a and adjust our classes to match that (inner div becomes .card)

  • Patterns are normal but still confusing
    • Usually 1em on top, 1em on bottom
  • border-left -> border: changes nothing
  • height: 100%: changes nothing
  • removing display: grid: makes margin 0

What the heck is going on here? The inspect tool reveals nothing, if anything it makes the issue more confusing. The div is offset from the anchor by 1em, but it's not clear why

Ideally, the margin is 0 (w/o display: grid style), but I can settle for an even 1em on both sides. I'm mostly curious why this behavior happens and what I can do to negate it.

Thank you wizards!


Solution

  • Wowee this is some strange behaviour.

    It looks like the margin-top on the p is flowing out the top of the grid but the grid is calculating it's own height based on including that margin, so that makes it look like the p has a margin-bottom that's 2em instead of 1em (it's not though).

    enter image description here

    It's weird behaviour but I think it's related to the way that margins collapse with adjacent elements.

    We can confirm this by adding display: inline-block to the p element (which prevents it from collapsing margins).

    Inline Block

    with position inline block

    So now that we know what's happening, what to do about it?

    If you can live with the display: inline-block on the p then that'll work. Otherwise you could kill the margin (p { margin: 0 }) and replace it with padding.

    Padding instead of Margin

    padding instead of margin