Responsive Card Grids Without Media Queries Using CSS Grid auto-fit
Use repeat(auto-fit, minmax()) and fr units to build card grids that reflow automatically, with a flexbox fallback for older browsers.
23 Aug 2026, 17:03 UTC

A card grid that keeps breaking at every breakpoint
You have a list of product cards. On a wide desktop screen, three columns fit comfortably. On a tablet, two columns work better. On a phone, one column is the only option. The usual response is a stack of media queries that redefine widths, percentages, or flex-basis values at arbitrary pixel cutoffs. The result is brittle: add a new card size or a sidebar, and the breakpoints drift out of sync.
The practical takeaway is that CSS Grid can decide column count for you. With repeat(auto-fit, minmax(200px, 1fr)), the browser creates as many columns as fit and stretches them to share leftover space equally. You can remove most card-grid media queries entirely.
What the declaration actually does
A grid container is an element with display: grid. Its direct children become grid items. The browser divides the container into tracks (columns and rows).
repeat(auto-fit, minmax(200px, 1fr)) works in three steps:
repeat()generates multiple column tracks instead of listing each one manually.auto-fitpacks as many tracks as possible into the container, then collapses any empty tracks so they do not occupy space.minmax(200px, 1fr)sets each column's minimum width to 200 pixels and its maximum to one fraction of the remaining free space.
The fr unit means "fraction of available space." If three columns fit, each gets roughly one-third of the space after gaps are subtracted. If the container narrows so only two columns meet the 200-pixel minimum, the browser drops to two columns automatically.
gap: 1rem adds gutters between tracks but not around the container's outer edge, which avoids the extra side margins that often appear with floated or inline-block grids.
Worked example: card grid with a flex fallback
This markup assumes a simple list of cards. Place the styles in your stylesheet or a <style> block on the page.
<ul class="card-grid">
<li class="card"><img src="thumb.jpg" alt=""><p>Card title</p></li>
<li class="card"><img src="thumb.jpg" alt=""><p>Card title</p></li>
<li class="card"><img src="thumb.jpg" alt=""><p>Card title</p></li>
</ul>
.card-grid {
/* Fallback for browsers without Grid support */
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
flex: 1 1 200px;
border: 1px solid #ccc;
border-radius: 4px;
padding: 1rem;
}
@supports (display: grid) {
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.card {
flex: none;
width: auto;
}
}
The @supports (display: grid) block is a feature query. Browsers that do not recognize Grid ignore the entire block, so they keep the flexbox layout. Browsers that do support Grid apply the two-column-or-more layout automatically.
No explicit row positions are required. Grid's auto-placement puts each card into the next available cell, so the list flows row by row without assigning grid-column or grid-row to individual items.
Verify the result and know the limits
Open the page in Chrome, Firefox, Edge, or Safari. Right-click the grid container and choose Inspect. In the Computed panel, confirm that display is grid. Resize the browser window and watch the column count change as the container crosses the width needed for another 200-pixel track plus gap. This should happen without any media query in your stylesheet.
To confirm the fallback works, temporarily comment out the @supports block and reload. The cards should still wrap using flexbox, though they will not stretch into equal grid tracks.
There are trade-offs. auto-fit collapses empty tracks, so a very wide container with only a few cards may show one or two stretched columns instead of several narrow ones. If you need to preserve empty column slots, use auto-fill instead. Also, Grid is unsupported in Internet Explorer 11 and some older mobile browsers, which is why the flex fallback matters. Finally, content inside a card that cannot shrink—such as a wide image or unbreakable string—can force a track wider than the 200-pixel minimum.
Closing checklist
- Use
repeat(auto-fit, minmax(200px, 1fr))for uniform card lists where every card should share the row equally. - Pair it with
gapfor gutters rather than margins on individual cards. - Wrap Grid styles in
@supports (display: grid)and provide a flexbox or block fallback. - Verify computed
display: gridin DevTools and confirm column count changes on resize. - Switch to
auto-fillonly if preserving empty tracks is more important than collapsing them.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.