6

This code uses CSS grid with minmax(30rem, 1fr).

grid-template-columns: repeat(auto-fill, minmax(30rem, 1fr));

Everything works fine, but when the viewport parent container gets smaller than 30rem, a horizontal scrollbar appears. I would need something like minmax(min(30rem, 100%), 1fr)). Any idea how to achieve that?

https://codepen.io/anon/pen/LmEyer

ul {
  list-style-type: none;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30rem, 1fr));
  grid-auto-rows: 1fr;
  grid-gap: 10px;
}

li {
  background-color: #aaa;
  padding: 0.5rem;
}
<ul class="list">
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
<ul>
mhchem
  • 288
  • 1
  • 18

2 Answers2

2

You answered the question yourself!! you can use the min() function to achieve this:

codepen

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

I recommend this article to learn more about combine clamp and min() with grid-template-column

Flamingo
  • 322
  • 1
  • 11
  • You are right. I guess the function nesting was not available 5 years ago. Or I did a when trying it out. – mhchem Apr 03 '23 at 15:24
1

Sounds like you have a breakpoint when the screen width is 30rem. That calls for a media query.

Add this to your code:

@media (max-width: 30rem) {
   ul { grid-template-columns: 1fr; }
}

revised codepen

ul {
  list-style-type: none;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30rem, 1fr));
  grid-auto-rows: 1fr;
  grid-gap: 10px;
}

li {
  background-color: #aaa;
  padding: 0.5rem;
}

@media (max-width: 30rem) {
  ul {
    grid-template-columns: 1fr;
  }
}
<ul class="list">
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
  <li>grid item</li>
<ul>
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    1. The media query should take the grid-gap into account. So it should read `@media (max-width: calc(30rem + 2 * 10px))`, but that is [not widely supported](https://stackoverflow.com/questions/23667208/calc-not-working-within-media-queries), currently. – mhchem Apr 20 '18 at 07:09
  • 2. Unfortunately, this only works if the grid is on root level. It does not work if this grid is in a container narrower than the viewport. (Yes, my original question was about viewport. But that was for simplicity.) – mhchem Apr 20 '18 at 07:11
  • 1
    No need to factor in a grid-column-gap (which only render *between* items). Once the screen reaches 30rem, there is only one column, and no gap. @mhchem – Michael Benjamin Apr 20 '18 at 16:23
  • 1. @Michael_B Yes and no. It's not the grid-gap, you are right about that. But 30rem is not the correct value to avoid scrollbars (tested your codepen in several browsers). In this case, it's the `body`'s margin that you have to factor in. – mhchem Apr 22 '18 at 06:02