18

Is there a way, without using media query, to limit the number of columns that get created, and combine that with auto-fit/fill?

For example:

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

Creates a wonderful, responsive layout. But imagine the design calls for a maximum of 3 columns -- even in wide browsers. It would happily show, 4, 5, more columns as space allows.

Using media query, I could specify big screens get:

grid-template-columns: 1fr 1fr 1fr;

And smaller screens get:

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

But that feels wrong. Is there a way to tell my grid layout to repeat up to a maximum of n times, and still use repeat and auto-fit/fill?

Update: This is not a duplicate of: How to limit the amount of columns in larger viewports with CSS Grid and auto-fill/fit?

I am asking how to make the code for the viewport also work for smaller viewports. The question (and answer) referenced above only gets to the starting point of my question.

Ted
  • 2,211
  • 2
  • 19
  • 27
  • Why do you think this feels wrong? I personally don't have negative feelings about this – yunzen Feb 27 '19 at 14:13
  • @yunzen I am trying to figure out if there is something elegant like "repeat-until(3, auto-fit, minmax())" that can make my grid limit the number of columns, but still be responsive. – Ted Feb 27 '19 at 14:22
  • @TylerH, I don't see how this post isn't a duplicate of https://stackoverflow.com/q/55281598/3597276. Re-opening. If the question is closed again, please provide an explanation. Thanks. – Michael Benjamin Jul 05 '23 at 22:07
  • 1
    @MichaelBenjamin See the discussion about it on the target, starting at https://stackoverflow.com/questions/55281598/css-grid-maximum-number-of-columns-without-media-queries tl;dr they are duplicates but this one is a better target, not vice versa. – TylerH Jul 05 '23 at 22:25

2 Answers2

16

CSS custom properties ('CSS variables') to the rescue

.grid {
  --repeat: auto-fit;
}
@media (min-width: calc(250px * 3)) {
  .grid {
    --repeat: 3;
  }
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--repeat, auto-fit), minmax(calc(250px * 1) , 1fr));
  grid-gap: 8px;
}

.grid .item {
  background-color: silver;
  padding: 8px;
}
<div class="grid">
  <div class="item">Lorem, ipsum.</div>
  <div class="item">Soluta, voluptatibus!</div>
  <div class="item">Reprehenderit, consequuntur.</div>
  <div class="item">Temporibus, veritatis!</div>
  <div class="item">Consequatur, voluptates.</div>
  <div class="item">Distinctio, adipisci.</div>
  <div class="item">Repellat, corrupti.</div>
  <div class="item">Quia, corporis.</div>
  <div class="item">Nobis, aut.</div>
  <div class="item">Dicta, officiis?</div>
  <div class="item">Voluptate, tempora?</div>
  <div class="item">Nihil, earum?</div>
  <div class="item">Placeat, aspernatur!</div>
  <div class="item">Officia, sunt?</div>
  <div class="item">Atque, temporibus!</div>
  <div class="item">Rerum, unde!</div>
  <div class="item">Hic, molestias!</div>
  <div class="item">Et, repellat!</div>
  <div class="item">Earum, itaque.</div>
  <div class="item">Doloribus, facilis.</div>
  <div class="item">Eius, alias!</div>
  <div class="item">Est, officia.</div>
  <div class="item">Ad, porro!</div>
  <div class="item">Ipsum, voluptates.</div>
  <div class="item">Animi, eligendi.</div>
  <div class="item">Tempore, hic!</div>
  <div class="item">Voluptatibus, illum.</div>
  <div class="item">Autem, cumque!</div>
  <div class="item">Cupiditate, minus!</div>
  <div class="item">Tenetur, aliquam.</div>
</div>

Remark

The asker wanted in his OP a solution which would not use media queries. This solution does use media queries, but in a somewhat different way. The only thing that is changed in the media query is the value of a CSS custom property.

We could even use a 'global' custom property with the :root selector

:root {
  --repeat: auto-fit;
}
@media (min-width: calc(250 * 3px)) {
  :root {
    --repeat: 3;
  }
}

One could think further and use custom properties in the media query condition itself, but unfortunately this does not work. (See this answer)

/* not working */
:root {
  --repeat: auto-fit;
  --max-columns: 3;
  --max-column-width: 250px;
}
/* Will not work: var is not allowed in media query condition */
@media (min-width: calc(var(--max-column-width) * var(--max-columns))) {
  :root {
    --repeat: var(--max-columns);
  }
}
yunzen
  • 32,854
  • 11
  • 73
  • 106
6

Just add a max-width to the container.

grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
max-width: 1280px;
Adam A Allalou
  • 1,503
  • 1
  • 8
  • 8