Reputation: 1248
I am looking for a way to automatically generate a grid, that always fills the available space, while shrinking the items until another item can be added.
Most responsive grid implementations use something link this:
grid-template-colums: repeat(auto-fill, minmax(120px, 1fr));
This works fine, except, that it uses the minimum value as the default image size, which results in interpolation of the images inside the grid. I want to do the opposite — set a max-width and shrink the images if necessary.
Let’s say my grid items should have a max-width of 400px. Here are some of the values, that I want to get:
400px available space: One image with a width of 400px
402px available space: Two images with a width of 201px
800px available space: Two images with a width of 400px
and so on …
Essentially I want to clamp my image between 200px and 400px and always use the biggest value possible. I guess I need something like this:
min(max(200px, 1fr), 400px)
The only way I was able to achieve this so far, was by generating some media queries.
/* This example adjusts items to a max-width of 400px with a 10px grid-gap.*/
@media (min-width: 401px) {
.grid {
grid-template-columns: repeat(auto-fill, calc((100% - 10px) / 2));
}
}
@media (min-width: 811px) {
.grid {
grid-template-columns: repeat(auto-fill, calc((100% - 20px) / 3));
}
}
I have written a Sass mixin to make this process more flexible, but this solution comes with some draw-backs:
I am looking for a way that does not have these drawbacks.
Edit:
Here is a CodePen of my current code. It should be easier to understand what I want to do, if you play around with it.
Upvotes: 4
Views: 3017
Reputation: 371221
Your media queries solution may be your best option, at this point.
Currently, CSS Grid does not provide for flexible minimums.
From the spec:
minmax(min, max)
Defines a size range greater than or equal to min and less than or equal to max.
If max < min, then max is ignored and
minmax(min,max)
is treated asmin
.As a maximum, a
<flex>
value sets the track’s flex factor; it is invalid as a minimum.Note: A future level of this spec may allow
<flex>
minimums, and will update the track sizing algorithm to account for this correctly
Have you considered flexbox instead:
.grid {
display: flex;
flex-wrap: wrap;
}
.grid > div {
flex: 1 0 200px; /* can grow, can't shrink, minimum width 200px */
max-width: 400px;
margin: 5px;
}
.grid-item {
width: 100%;
height: auto;
}
<div class="grid">
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
<div><img src="http://placehold.it/400x300" alt="" class="grid-item"></div>
</div>
Upvotes: 2