Fully responsive items with CSS grid and auto-fit minmax
Asked Answered
T

3

9

The use of grid-template-columns: repeat(auto-fit, minmax(600px, 1fr)) makes it easy to build a responsive CSS grid. The container will be filled with as many elements fit into a row, without using a media query.

.container {
  display: grid;
  grid-gap: 5px;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
}

.item {
  height: 100px;
  background: #ccc;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

The problem is that the items are wider than the screen when the screen is smaller than the min-value specified in minmax(). You can fix this by adding a media query at 400px, but this only works when you know that there's no content around the container. And that's almost impossible when the container could be placed anywhere.

Is there a way or property to tell the items that they should never be wider than 100%?

Something like: Fill the container with as many 400px items as possible, but ensure that non of them gets wider than 100% of the width of the container.

CodePen Demo

Tripedal answered 26/12, 2017 at 17:18 Comment(5)
More about auto-fill and auto-fit: blog.jonstodle.com/…Tripedal
Since there are other elements on the page, your media query would have to be based on the entire layout, not just this one container. So when all content on the page squeezes this container down to 400px, then trigger the media query...Potto
Otherwise, use a script that switches the value of grid-template-columns when it detects a width of 400px on the container.Potto
@Michael_B That's correct. The media query only works when the container fills the whole page. This is usually not the case. A script that implements "element queries" could solve this. Looks like it isn't possible in CSS only :(Tripedal
This is not really related to CSS grids, as it's true with any responsive-width element that uses a min-width. It would only be possible using element queries (polyfill here)Blackfish
L
3

You should change grid-template-columns to grid-template-columns: repeat(auto-fit, minmax(min-content, 400px)) because minmax works this way: it tries to apply max value and if fails it applies minimum. But in this you can get blank space in your grid to the right. Demo:

.container {
  display: grid;
  grid-gap: 5px;
  grid-template-columns: repeat(auto-fit, minmax(min-content, 400px));
}

.item {
  height: 100px;
  background: #ccc;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>
Leatherleaf answered 4/3, 2018 at 22:19 Comment(0)
B
0

Fill the container with as many 400px items as possible, but ensure that non of them gets wider than 100% of the width of the container.

For that you can use the "max-content" property, in your example this would be:

.unresponsive {
    grid-template-columns: repeat(auto-fit, minmax(400px, auto));
    grid-auto-columns: max-content;
}
Batholomew answered 27/12, 2017 at 17:32 Comment(1)
Good idea, but it's not working. I guess it's because there're no implicitly-created grid columns (grid-auto-columns) when the template columns auto-fit/fill. max-content inside the minmax didn't work for me either.Tripedal
O
0

tldr; add min(X, 100%) to minmax()

To fill a grid container with as many X-size columns as fit, without any overflow in small viewports, use:

.container {
  grid-template-columns: repeat(auto-fit, minmax(min(X, 100%), 1fr));
}

The magic is in passing min(X, 100%) as an argument to minmax(). The 100% ensures that a column never takes more than 100% of the container's width.

For the specific case OP described, this code would give the desired result:

.container {
  display: grid;
  grid-gap: 5px;
  grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr));
}

CodePen Demo

Omeara answered 24/6 at 21:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.