Chrome / Firefox percentage height differences in CSS Grid

不羁岁月 提交于 2019-12-19 09:53:55

问题


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


回答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:

  • Chrome / Safari not filling 100% height of flex parent
  • Working with the CSS height property and percentage values

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>



回答2:


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



来源:https://stackoverflow.com/questions/53655150/chrome-firefox-percentage-height-differences-in-css-grid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!