3

If I set a variable value for grid-gap like 10% the padding-bottom of the parent (<div id="grid">) starts flowing inside the children (<div class="grid-item">). Why is that and how can I prevent this behavior?

Here is an minimal example:

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

#grid {
  padding-bottom: 100px;
  display: grid;
  grid-gap: 10%;
  grid-template-columns: 100px;
}

.grid-item img {
  width: 100%;
}
<div id="grid">
  <div class="grid-item"><img src="https://cdn.sstatic.net/Img/teams/overview/secure.png?v=03c691959884">
    <h3>Stack Overflow</h3>
  </div>
  <div class="grid-item"><img src="https://cdn.sstatic.net/Img/teams/overview/secure.png?v=03c691959884">
    <h3>Stack Overflow</h3>
  </div>
</div>

You can use the Dev-Tools to inspect the grid-parent (<div id="grid">) and look at the padding or see this screenshot to see the issue (padding (green) infringing on the space of the grid-elements (dashed boxes)):

leonheess
  • 16,068
  • 14
  • 77
  • 112
  • 1
    grid-gap:10vw or 10vh would probably work like you expected 10% would ? there is no padding that i can see here – G-Cyrillus Nov 03 '19 at 11:26
  • @G-Cyr I added a screenshot for clarity. I would like to use 10% if possible. – leonheess Nov 03 '19 at 11:40
  • okay, use `grid-gap: 10vh 10vw;` you should have the result expected without miscalculation from the browser. here is a demo with both values . % and vh/vw units https://codepen.io/gc-nomade/pen/ZEEvZEL – G-Cyrillus Nov 03 '19 at 11:46
  • @G-Cyr I know I can circumvent the problem by not using %. I still would like to understand the issue - is this a bug? – leonheess Nov 03 '19 at 11:49
  • it probably is a bug about % calculation, IE6, years ago, told me to go for an alternative instead trying understand and curing a bug (mainly the haslayout calculation), it can be a hudge waste of time. It doesn't work, okay then, i'll do another way . – G-Cyrillus Nov 03 '19 at 11:55
  • 1
    @G-Cyr not really a bug but it's due to how percentage value are calculated. As you know we need a reference and for the gap its the height which is auto so we first find the height without the gap, then we calculate the gap and we add the gap to the previous height (we stop here or we will have an infinite loop) --> we have an overflow – Temani Afif Nov 03 '19 at 12:56
  • @temaniafif What is noticeable here is that the gap value is removed at bottom from padding. If no padding and border on the grid, you can see the last row overflowing .. 10% .this looks like à bug to me at that point – G-Cyrillus Nov 03 '19 at 13:07
  • @G-Cyr, it's not removed from the padding but overflowing the padding since the height doesn't consider the padding-box but only the content-box .. so in all the cases it will overflow either the padding or the border if they are defined by 10% of the height of the content box – Temani Afif Nov 03 '19 at 13:09
  • @G-Cyr, *"What is noticeable here is that the gap value is removed at bottom..."* There was never a gap value at the bottom. Gaps are only between items, never between items and the container. – Michael Benjamin Nov 03 '19 at 13:12
  • (Excuse me if I misunderstood your comment.) – Michael Benjamin Nov 03 '19 at 13:12
  • @Michael_B i meant the gap % value set in CSS , not a supposed gap standing on the inside edge of the grid box . this only happens while using % for the gap. ;) it brings a miscalculation of the final box's height minus that gap (padding-bottom or not). – G-Cyrillus Nov 03 '19 at 13:51
  • @Michael_B actually, grid-gap %value x number of ros - 1 (every gap generated are added and removed from the height (supposed to be at bottom of the las row / to wrap the last row) .. my english so average is not really clear indeed :) – G-Cyrillus Nov 03 '19 at 13:58
  • @TemaniAfif Somehow I only have this issue in Chrome which makes me believe it's a bug as well - do you think I should report it? – leonheess Nov 03 '19 at 14:02
  • @leonheess i have this bug in both ff & chrome , % gap value is correctly calculated and exactly removed at bottom about 35px for 2 rows , about 50px for 2 rows ,2 row, 35px removed (1 gap) , 3 rows , 100px removed (2 gaps) . – G-Cyrillus Nov 03 '19 at 14:06
  • It's because the spec defining this behavior is still in Draft so not all the browser are implementing this kind of *cycle* calculation. If you read the duplicate and the links I shared you will see that this behavior is logical (1) we first do the calculation without gap (2) we calculate the gap (3) we add the gap to the height --> you will always have an overflow. If you don't notice this in some browser it means they are simply ignoring the gap or doing another kind of calculation – Temani Afif Nov 03 '19 at 14:15
  • @G-Cyr because there is a cycle that the browser cannot handle. The gap can only be calculated after calculating the height without the gap and then we cannot recalculate the height again because it will never end. Here is a basic example to illustarte: https://jsfiddle.net/dtsgfx54/ .. notice how the height of the grid never change and you will see that the gap is considering 150px as reference (the height of the grid items). The first grid is the first step of the calculating (wiouth gap) and then the gap is added because now we have a reference to resolve the percentage – Temani Afif Nov 03 '19 at 14:27
  • @TemaniAfif@G-Cyr I found this to be very enlightening: https://blogs.igalia.com/mrego/2018/08/10/changes-on-css-grid-layout-in-percentages-and-indefinite-height/ – leonheess Nov 05 '19 at 17:38

1 Answers1

1

Here's my guess, based on my knowledge of the cascade, percentage lengths and the grid sizing algorithm. I haven't found anything official that specifically addresses this issue so, again, this is an extrapolation.

For a percentage height to work, when there is no explicit height defined on the parent container, the browser first needs to render all other lengths. This way it arrives at the actual size of the container and can answer the question: "10% of what?".

Hence, the browser first renders the items and the padding-bottom: 100px.

Now it can calculate grid-gap: 10% or, more specifically, the row-gap: 10% component (a percentage height).

Because all other sizes are already in place, this additional 10% height forces the lower item to intrude into the fixed padding space.

In support of this theory, if we set a height on the container, which now provides a clear reference point for the percentage row height, the rule can be rendered in sequence with the others (i.e., there's no need for the percentage height to be rendered at the end), and the overlap is eliminated in most cases. (There will still be an overlap in shorter screens because the padding has a fixed height of 100px.)

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

#grid {
  padding-bottom: 100px;
  display: grid;
  grid-gap: 10%;
  grid-template-columns: 100px;
  height: 100vh; /* new */
}

.grid-item img {
  width: 100%;
}
<div id="grid">
  <div class="grid-item"><img src="https://cdn.sstatic.net/Img/teams/overview/secure.png?v=03c691959884">
    <h3>Stack Overflow</h3>
  </div>
  <div class="grid-item"><img src="https://cdn.sstatic.net/Img/teams/overview/secure.png?v=03c691959884">
    <h3>Stack Overflow</h3>
  </div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    I guess everything is defined here: https://www.w3.org/TR/css-sizing-3/#percentage-sizing .. I was able to approximately understand what i happening but too difficult to explain that part of the spec. – Temani Afif Nov 03 '19 at 13:17
  • 1
    remind me an old question by the way ;) https://stackoverflow.com/q/51962136/8620333 – Temani Afif Nov 03 '19 at 13:27
  • 1
    Yeah, would need some time to peruse that section, build tests and run across browsers, with no guarantee that browsers adhere to the spec, or that we interpreted the language correctly. Not on a sunny, warm Sunday morning. Have a nice day! – Michael Benjamin Nov 03 '19 at 13:27
  • When you use a ruler , on the 2 row example of the op, you can see that the gap is 10% of the length in between the top box of first row and the bottom box of the second row. what's missing from the 100px is those 10% gap. Make that box 3 rows , gaps is increased to match distance from first to las row but those 2 gaps are removed also from the 100px , make it 4 rows and the last row stands partially outside., 5 rows and you have partially a gap and the last row totally outside of the grid box. :( https://codepen.io/gc-nomade/pen/eYYyayX to me, this is a bug ;) – G-Cyrillus Nov 03 '19 at 14:14