I know this sounds like the typical problem of using percentage values, but it’s different. At least at first glance.
Here’s the situation: we have a grid with some elements:
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
And the grid has a max-width
but it’s scrollable:
.container {
display: grid;
grid-template-columns: repeat(10, max-content);
max-width: 400px;
overflow-x: auto;
}
Let’s also define how an item should be so they take up some space:
.item {
background-color: navy;
width: 100px;
aspect-ratio: 1 / 1;
}
Now, this works as expected: I can scroll to the right and I can only see the contained items inside the grid.
But if I add gap: 5px;
to the grid and I scroll the same way, the farthest pixels to the right inside the scrollable area are suddenly not occupied by the elements. These are "extra pixels" added by the gap, somehow.
You can see it here.
What I’ve also noticed is that this only happens if there are fewer items than declared columns (e.g. if we change grid-template-columns
to repeat(4, max-content);
and max-width
to 300px;
it works fine.)
2
Answers
It turns out the
gap
is applied to the columns and rows, not the contained elements inside the grid. The grid in the snippet is 10 columns wide, and only half of them have elements "in them." The gaps are 10 pixels long, and there are 5 empty columns in a row, for a total of 50 blank pixels at the end of the grid (5 * 10 = 50.)gap adds extra space to the total width of the grid that can cause overflow and create extra space on the right side of your scrollable area, especially when the number of items is less than the number of columns specified in
grid-template-columns
.For this, use a combination of
grid-template-columns
with1fr
andgrid-auto-flow
withcolumn
, so this will create a responsive grid that adjusts the number of columns based on the container width and also grid items are filled in a column-wise manner.