Search code examples
csscss-grid

Why does grid-gap cause an overflow?


Why do I have an overflow on the X axis in the following snippet?

The overflow is generated once I apply grid-gap: 10px on my .body grid container.

div:not(.header):not(.body):not(.row) {
  border: 1px solid grey;
}

.header {
  margin-top: 20px;
  display: grid;
  grid-gap: 10px;
  grid-template-areas: "header-left header-right-up" "header-left header-right-down";
  grid-template-rows: 40px 40px;
  grid-template-columns: minmax(50px, 200px) auto;
}

.header-left {
  grid-area: header-left;
}

.header-right-up {
  grid-area: header-right-up;
}

.header-right-down {
  grid-area: header-right-down;
}

.body {
  margin-top: 20px;
  display: grid;
  grid-template-columns: 25% 50% 25%;
  grid-auto-rows: 80px; 
  grid-gap: 10px;
}

.row-left {
}

.row-center {
}

.row-right {
}
<div class="header">
  <div class="header-left">image</div>
  <div class="header-right-up">content</div>
  <div class="header-right-down">long content</div>
</div>

<div class="body">
    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>

    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>

    <div class="row-left"></div>
    <div class="row-center"></div>
    <div class="row-right"></div>
  </div>
</div>

https://codepen.io/anon/pen/WdJExz?editors=1100


Solution

  • Short Answer

    Because the width of the columns plus the width of the gaps is greater than 100%.


    Explanation

    You have a 3-column grid container (.body):

    grid-template-columns: 25% 50% 25%
    

    The total width of those columns is 100%.

    You're then adding gutters between the columns (and rows):

    grid-gap: 10px
    

    which is shorthand for:

    grid-column-gap: 10px;
    grid-row-gap: 10px;
    

    So this becomes the width calculation:

    25% + 50% + 25% + 10px + 10px
    

    Hence,

    100% + 20px > 100%, which results in an overflow condition
    

    Note that the grid-*-gap properties apply only between grid items – never between items and the container. That's why we calculate two grid gaps, not four.

    As a solution, instead of percentage units, try using fr units, which apply only to free space. This means that fr lengths are calculated after any grid-gap lengths are applied.

    grid-template-columns: 1fr 2fr 1fr
    

    div:not(.header):not(.body):not(.row) {
      border: 1px solid grey;
    }
    
    .header {
      margin-top: 20px;
      display: grid;
      grid-gap: 10px;
      grid-template-areas: "header-left header-right-up" "header-left header-right-down";
      grid-template-rows: 40px 40px;
      grid-template-columns: minmax(50px, 200px) auto;
    }
    
    .header-left {
      grid-area: header-left;
    }
    
    .header-right-up {
      grid-area: header-right-up;
    }
    
    .header-right-down {
      grid-area: header-right-down;
    }
    
    .body {
      margin-top: 20px;
      display: grid;
      grid-template-columns: 1fr 2fr 1fr; /* ADJUSTMENT */
      grid-auto-rows: 80px;
      grid-gap: 10px;
    }
    
    .row-left {}
    
    .row-center {}
    
    .row-right {}
    <div class="header">
      <div class="header-left">image</div>
      <div class="header-right-up">content</div>
      <div class="header-right-down">long content</div>
    </div>
    
    <div class="body">
      <div class="row-left"></div>
      <div class="row-center"></div>
      <div class="row-right"></div>
    
      <div class="row-left"></div>
      <div class="row-center"></div>
      <div class="row-right"></div>
    
      <div class="row-left"></div>
      <div class="row-center"></div>
      <div class="row-right"></div>
    </div>

    revised codepen demo

    More details here: The difference between percentage and fr units