This one line builds a responsive grid:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
}
Read it in plain words: “Make as many columns as will fit, each at least 160px wide, and let them share the remaining space equally.”
<style>
.grid > div { background: #d0e8f2; border: 1px solid #1a5276; padding: 10px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; }
</style>
<div class="grid"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div></div>
Make the browser window narrower or wider. The number of columns changes with it, with no media query. In this small panel it chooses 3 or 4 columns, on a laptop screen with a bigger area it would pick more.
auto-fit vs auto-fill
They differ only when there are fewer items than columns that could fit.
auto-fillkeeps the empty columns. The items stay at their size and blank tracks fill the rest of the row.auto-fitcollapses the empty columns, so the items stretch to fill the row.
<style>
.grid > div { background: #d0e8f2; border: 1px solid #1a5276; padding: 10px; }
.grid { display: grid; gap: 8px; margin-bottom: 10px; }
.fit { grid-template-columns: repeat(auto-fit, minmax(70px, 1fr)); }
.fill { grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); }
</style>
<p>auto-fit: two items stretch</p>
<div class="grid fit"><div>1</div><div>2</div></div>
<p>auto-fill: two items keep their size</p>
<div class="grid fill"><div>1</div><div>2</div></div>
For card grids, auto-fit is usually the right choice. Use auto-fill when you want items to stay a consistent size even if there are only a few.
A mistake that breaks it
If the minimum is bigger than the container on small screens (for example minmax(300px, 1fr) in a 280px wide area), the grid overflows. Use min(100%, 300px) for the minimum:
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
This uses min(), so a single column never gets wider than its container.