Afterlame
Afterlame

Reputation: 1248

Responsive css grid layout with max-width items

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

Answers (1)

Michael Benjamin
Michael Benjamin

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 as min.

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>

revised codepen

Upvotes: 2

Related Questions