2

Why does explicitly setting two CSS Grid columns to 50% each create a horizontal scroll beyond 100% of the viewport width?

This codepen shows the behavior I'm asking about.

Basically, when the grid is set to the following css, it produces a two-column layout with no forced horizontal scroll beyond the viewport width:

.grid {
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: 50%;
  grid-template-areas: 'item item';
}

When grid-template-columns is changed to explicitly set both column widths, the result is a two-column layout with a horizontal scroll:

.grid {
  grid-template-columns: 50% 50%;
}

Why is the horizontal scroll present in the second context, but not the first?

edit: <aside>I seem to remember flexbox behaves in a similar fashion</aside>

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

.grid {
  padding-top: 1rem;
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: 50%;
  grid-template-areas: 'item item';
}

/* WHY THE HORIZONTAL SCROLL 
   WHEN LINES 21-23 ARE
   UNCOMMENTED?! */

/* .grid {
  grid-template-columns: 50% 50%;
} */

.item {
  padding: 2rem;
  border: 2px solid black;
  border-radius: 0.25rem;
}

.p1 {
  padding: .5rem;
}

code {
  padding: .5rem;
  background: gray;
  color: white;
  font-weight: regular;
}
<header class="p1">
  <h1>Why does the horizontal scroll happen when <code>.grid { grid-template-columns: 50% 50%; }</code></h1>
  <p>Uncomment lines 21-23 in the CSS of this codepen to set the above <code>.grid</code> css rule. See this <a href="https://stackoverflow.com/q/52374483/2145103">Stack Overflow post for discussion.</a></p>
</header>
<div class="grid">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>
Brian Zelip
  • 2,909
  • 4
  • 33
  • 45
  • 1
    Work with fr units: grid-template-columns: 1fr 1fr; I don't have the specifics at hand, but AFAIK, fr is a "flex unit" that refers to the amount of remaining space (discounting padding, etc.). Apparently, percentual values don't take those into consideration and the effective sizes overflow the horizontal client size. – Zunino Sep 17 '18 at 19:38
  • 1
    a similar issue : https://stackoverflow.com/questions/52113420/display-grid-and-position-fixed-goes-out-of-body/52115646#52115646 – Temani Afif Sep 17 '18 at 23:17

1 Answers1

6

Your code (version 1):

.grid {
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: 50%;
  grid-template-areas: 'item item';
}

This will not overflow the container.

Two explicit columns are created by grid-template-areas.

The first column's width is set by grid-template-columns to 50%.

The second column's width is not set. Therefore, grid-template-columns computes to none (spec).

The grid spec doesn't appear to go into detail about how grid-template-columns: none should apply to an explicit track. But here's what Chrome, Firefox and Edge are doing:

  • Even though the second column is explicit, because it's defined by grid-template-areas, for track sizing purposes it's considered implicit, because grid-template-columns hasn't been defined.

  • Therefore, the second column is being sized by grid-auto-columns, the sizing function for implicit columns (demo).

  • The default value of grid-auto-columns is auto (spec), which renders a lot like 1fr in many cases, by definition).

  • So the second column is only consuming remaining space, which causes it to fill the row. No overflow is triggered.


Your code (version 2):

.grid {
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: 50% 50%;
  grid-template-areas: 'item item';
}

This one is much easier to follow. Yes, this will clearly overflow the container:

50% + 50% + 1rem > 100%

Related:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701