3

Please note, the following problem can be solved by using fr units instead of % and auto, but I am looking for an explanation as to why the problem occurs in the first place.

In my code below,

Firefox: Does not obey the values for grid-template-rows. Applies an equal height to each row but the grid items do not overflow the container.

Chrome: Seems to obey the grid-template-rows property but the grid items overflow the container.

Initially I thought the issue was with % but it is an allowable unit for the row. I swapped out the auto value for 10% but that created its own problem.

I've looked at the documentation but I'm missing something.

Anyone have a straight-forward explanation?

body {
  margin: 40px;
}

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 30% 30% 30%;
  grid-template-rows: 30% auto 60%;
  background-color: #f00;
  color: #444;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
}
<div class="wrapper">
  <div class="box">A</div>
  <div class="box">B</div>
  <div class="box">C</div>
  <div class="box">D</div>
  <div class="box">E</div>
  <div class="box">F</div>
  <div class="box">G</div>
  <div class="box">H</div>
  <div class="box">I</div>
</div>

Codepen

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
groober
  • 113
  • 10
  • 1
    I'm pretty sure this is a known issue where the % value is calculated differently by different broswers on rendering. Can't find it now...but I'm sure I've seen it before. – Paulie_D Dec 06 '18 at 16:17
  • 1
    Then again - https://stackoverflow.com/questions/45090726/the-difference-between-percentage-and-fr-units-in-css-grid-layout – Paulie_D Dec 06 '18 at 16:18

2 Answers2

1

Initially I thought the issue was with % but it is an allowable unit for the row. I swapped out the auto value for 10% but that created its own problem. Anyone have a straight-forward explanation?

The problem actually is the use of % units.

The straightforward explanation is that percentage lengths are processed differently across browsers when there is no defined or inherited length on the parent container.

Therefore, because the grid container has no defined height, browsers will render the row heights, which are defined with percentages, inconsistently.

These variations are explored in detail in these posts:

The simple solution is to define a height on the container. In my example below, I've added height: 300px to .wrapper. Now the rows render the same across browsers.

.wrapper {
  height: 300px; /* new */
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 30% 30% 30%;
  grid-template-rows: 30% auto 60%;
  background-color: #f00;
  color: #444;
}

.box {
  background-color: lightblue;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
}
<div class="wrapper">
  <div class="box">A</div>
  <div class="box">B</div>
  <div class="box">C</div>
  <div class="box">D</div>
  <div class="box">E</div>
  <div class="box">F</div>
  <div class="box">G</div>
  <div class="box">H</div>
  <div class="box">I</div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
0

Chrome: Seems to obey the grid-template-rows property but the grid items overflow the container.

I would better say that chrome is doing an effort to have this working as the calculation is somehow complex and we have a cycle. Basically percentage value need to be resolved and initially (since there is no height defined) the browser cannot resolve the values of grid-template-rows so it will first cacluate the height of the wrapper based on its content (ignoring grid-template-rows) and we will obtain something like below:

console.log(document.querySelector('.wrapper').offsetHeight);
body {
  margin: 40px;
}

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 30% 30% 30%;
  /*grid-template-rows: 30% auto 60%;*/
  background-color: #f00;
  color: #444;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
}
<div class="wrapper">
  <div class="box">A</div>
  <div class="box">B</div>
  <div class="box">C</div>
  <div class="box">D</div>
  <div class="box">E</div>
  <div class="box">F</div>
  <div class="box">G</div>
  <div class="box">H</div>
  <div class="box">I</div>
</div>

This is the step at where Firefox is stopping but chrome will try to do more! Note the value of the height we obtained (194px). Now we can resolve the percentage values based on this value and you will have this:

console.log(document.querySelector('.wrapper').offsetHeight);
console.log(document.querySelector('.box:first-child').offsetHeight);
console.log(document.querySelector('.box:last-child').offsetHeight);
body {
  margin: 40px;
}

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 30% 30% 30%;
  grid-template-rows: 30% auto 60%;
  background-color: #f00;
  color: #444;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
}
<div class="wrapper">
  <div class="box">A</div>
  <div class="box">B</div>
  <div class="box">C</div>
  <div class="box">D</div>
  <div class="box">E</div>
  <div class="box">F</div>
  <div class="box">G</div>
  <div class="box">H</div>
  <div class="box">I</div>
</div>

Note how the first element (the first row) is having a height equal to 58px (0.3 * 194px) and how the last child (the last row) is having a height equal to 117px (0.6 * 194px). Logically the second row should have a height of 194px - 58px - 117px - 20px(gap) = -1 which is not enough so it will have a bigger height thus the overflow.

The overflow isn't really an issue but a side effect of this complex calculation and you will always have it unless you define a percentage value for each row less than (100% - 20px/3 = 33.33% - 6.67px).

console.log(document.querySelector('.wrapper').offsetHeight);
console.log(document.querySelector('.box:first-child').offsetHeight);
console.log(document.querySelector('.box:last-child').offsetHeight);
body {
  margin: 40px;
}

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 30% 30% 30%;
  grid-template-rows: 20% 20% 20%;
  background-color: #f00;
  color: #444;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
}
<div class="wrapper">
  <div class="box">A</div>
  <div class="box">B</div>
  <div class="box">C</div>
  <div class="box">D</div>
  <div class="box">E</div>
  <div class="box">F</div>
  <div class="box">G</div>
  <div class="box">H</div>
  <div class="box">I</div>
</div>

Also the browser won't get back to fix this issue by increasing the height of the wrapper as we will have a cycle since grid-template-rows was defined based on it.


Similar question: Grid gap percentage without height

Temani Afif
  • 245,468
  • 26
  • 309
  • 415