Would you use Flexbox or CSS Grid for an e commerce product layout with three columns?
CSS Grid. Product grids are inherently 2D (rows AND columns of equal-sized cards), and Grid handles that natively with one rule: 'grid-template-columns: repeat(auto-fill, minmax(240px, 1fr))'. It gives equal column widths, fluid responsiveness without media queries, and aligned rows automatically. Flexbox is 1D — to fake a grid you fight wrap behavior, leftover-item alignment, and equal heights. Use Flexbox inside each card; Grid for the layout.
Short answer: CSS Grid. Product listings are a textbook 2D layout — rows and columns of equal-sized cards — and that's exactly what Grid was designed for.
The Grid solution
.products {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 16px;
}That's the whole layout. Three things it gives you for free:
- Equal column widths. Every card is the same width; cards never stretch unevenly because of content differences.
- Auto-responsive.
auto-fill+minmaxpacks as many 240px+ columns as fit, then flexes them to fill the row. No media queries needed for "3 cols on desktop, 2 on tablet, 1 on mobile." - Aligned rows. Items in the same row share a height — no jagged baselines when one card has a longer title.
Why Flexbox is the worse choice here
Flexbox is 1D. To force a grid out of it you write:
.products { display: flex; flex-wrap: wrap; gap: 16px; }
.products > * { flex: 0 0 calc(33.333% - 11px); }Now the problems:
- Leftover-item alignment. 10 items in a 3-col layout = 1 orphan on the last row, stretched or left-aligned awkwardly. Grid keeps it the same width as the others.
- Different per-breakpoint math. Every breakpoint needs a new
flex-basiscalc. Grid'sauto-fillcovers all sizes in one rule. - Cross-row alignment is impossible. If row 1 has a tall card, row 2 cards don't align to row 1's tracks. Grid does.
- Gap math leaks into widths.
calc(33.333% - 11px)is a fragile hack that breaks if you change the gap.
The right division of labor
Grid for the page layout, Flexbox for the card internals:
.product-card {
display: flex;
flex-direction: column;
}
.product-card .footer { margin-top: auto; } /* pin price + button to bottom */This is the canonical pattern: Grid for 2D macro layout, Flex for 1D micro alignment inside each cell.
When Flexbox actually wins
- A nav bar (1D, items have varying widths).
- A toolbar with a "push the last item right" requirement (
margin-left: auto). - Anywhere items are inherently different sizes and should pack naturally.
A product grid is none of these.
Follow-up questions
- •How would you handle a 'featured' product that spans 2 columns?
- •How do you ensure all cards have equal heights when content varies?
- •What's the difference between auto-fill and auto-fit?
- •How would you add a sidebar with filters next to the grid?
Common mistakes
- •Using percentage widths with flex and forgetting to subtract gap — breaks when gap or column count changes.
- •Using auto-fit instead of auto-fill — auto-fit collapses empty tracks, so 1 item stretches across the full width.
- •Setting fixed heights on cards instead of letting Grid equalize them.
- •Using media queries to swap column counts when minmax() + auto-fill would do it implicitly.
- •Putting display:flex on the grid container itself, then complaining Grid 'doesn't work.'
Performance considerations
- •Both layout engines are highly optimized in modern browsers; the perf delta is negligible for typical product grids (<500 items). For very large lists (1000+), neither matters — you need virtualization (react-window) and Grid still wins because windowed rows compute item geometry trivially.
Edge cases
- •Last-row orphans: Grid keeps them the same width as siblings; Flex stretches or left-aligns them.
- •Variable card heights — Grid aligns by row, Flex doesn't.
- •Very narrow viewports — minmax(240px, 1fr) on a 320px screen still gives 1 column, no overflow.
- •Mixed-span items (a hero card spanning 2 cols) — trivial in Grid via grid-column: span 2; awkward in Flex.
Real-world examples
- •Amazon, Shopify, and most e-commerce product listings use Grid for the product matrix.
- •Pinterest's masonry layout is the rare case where you need CSS columns or a JS masonry library — neither Grid nor Flex handles uneven heights well.
- •Image galleries (Unsplash, Google Photos) — Grid with auto-fill is the standard.