Flexbox vs. CSS Grid: decide by the content
The design shows two cards, but the content may have more. Choose Flexbox or Grid by asking what happens when items are added.
By Frontsiter · Published · 3 min read
The problem
Many developers build exactly what the Figma file shows. The design shows two cards in an auto layout row, so they build a Flexbox row with two equal cards, and it matches the design. Then a third card is added, and the layout breaks. Flexbox did what it was built to do. The mistake was building without asking how many cards the content can have.
The design: two cards
A Flexbox row matches the design.
A third card, Flexbox row
The cards squeeze into one row.
A third card, Flexbox with wrapping
The third card stretches across the full width.
A third card, Grid with two columns
The third card starts a new row at the same width.
Options compared
| Criteria | Flexbox | Grid |
|---|---|---|
| A fixed set in one row (logo and links in a header) | StrongEach item is as wide as its content | MixedWorks, but you define a column for each item |
| Items added later, each as wide as its text (tags) | StrongItems wrap to a new line at their own width | WeakEvery item gets the same column width |
| Items added later, two per row (cards) | WeakA third card squeezes in or stretches across the row | StrongA third card starts a new row at the same width |
| The content inside one card | StrongOne rule keeps the link at the bottom | MixedWorks, but you define a row for each part |
The trade-off
Neither one is better. Each one fits a different kind of content. Flexbox works from the content out. Each item takes the space its content needs, and each wrapped line is laid out on its own, so items on different lines do not line up. Grid works from the layout in. You define the columns, and every item fills one, however many items arrive. The cost is that you choose the columns up front, which suits cards and does not suit tags.
How to set it up
Answer the two questions first. If the design does not answer them, ask the designer how the section looks with one item, with five, and with a very long title. Then, in your stylesheet:
/* Tags: any number, each as wide as its text. */
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
/* Cards: any number, one per row on phones, two from 40rem. */
.cards {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
}
@media (min-width: 40rem) {
.cards {
grid-template-columns: repeat(2, 1fr);
}
}
/* Inside each card: the link stays at the bottom. */
.card {
display: flex;
flex-direction: column;
overflow-wrap: anywhere; /* a long word or link wraps instead of widening the card */
}
.card-link {
margin-top: auto;
}For as many cards per row as fit, use repeat(auto-fill, minmax(min(16rem, 100%), 1fr)) for the columns.
Then test with long content, a step many developers skip. Normal words wrap on their own, but a long link or product code does not. By default, Flexbox and Grid items never shrink below their longest word, so the card grows wider than its column; overflow-wrap: anywhere fixes it. For a one-line title with an ellipsis, also give its flex item min-width: 0, or use minmax(0, 1fr) for grid columns.
When to choose something else
Use Flexbox with flex-wrap: wrap and justify-content: center when a short last row should sit in the center, such as three logos under four. Grid cannot center a last row that is not full.
In Frontsiter's first version, the homepage places its three cards with Grid, and each card uses Flexbox to keep its link at the bottom.
