CSS Flexbox vs Grid: Which Layout System Should You Use?
Both Flexbox and CSS Grid can produce similar results, which is why developers reach for the wrong one half the time. The difference comes down to one dimension vs two — and knowing which one you are dealing with makes the choice obvious.
The One-Sentence Rule
Use Flexbox when you are laying out items in one direction (a row or a column). Use CSS Grid when you need to control layout in two directions at once (rows and columns simultaneously).
That is genuinely the whole decision. Everything else is an elaboration on why that rule works in practice.
What Flexbox Is Actually Good At
Flexbox was designed for distributing space along a single axis. Its killer feature is that items can grow, shrink, and wrap naturally without you specifying exact dimensions for each one.
These are the cases where Flexbox is the right choice:
- Navigation bars — a row of links where you want certain items pushed to the right (
margin-left: auto) or spaced evenly (justify-content: space-between) - Card rows where each card has equal height regardless of content length (
align-items: stretchhandles this automatically) - Centering an element horizontally and vertically inside a container — three lines of CSS:
display: flex; justify-content: center; align-items: center - Button groups, icon + label combinations, and any component where children need to sit side by side with some spacing
- Wrapping lists where you want items to wrap to the next line when there is no more space (
flex-wrap: wrap)
.navbar {
display: flex;
align-items: center;
gap: 1rem;
}
.navbar .logo { margin-right: auto; }
/* logo stays left, links stay right */
What CSS Grid Is Actually Good At
Grid was designed for two-dimensional layouts — you define both rows and columns, and you can place items precisely into cells, span multiple rows or columns, and create gaps in both directions.
These are the cases where Grid is the right choice:
- Page layouts — header, sidebar, main content, footer all positioned relative to each other
- Magazine or dashboard layouts where different items take up different amounts of space
- Image galleries with a consistent grid structure regardless of image size
- Form layouts where labels and inputs need to align both horizontally and vertically
- Any layout where you are thinking about rows AND columns at the same time
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100dvh;
}
Side-by-Side Example: A Card Grid
This is where the confusion happens. Both systems can create a row of cards:
.card-row {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.card { flex: 1 1 280px; }
With Grid:
.card-row {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1rem;
}
Both work. The Grid version is usually preferred here because auto-fill with minmax gives you more predictable column behavior — each column is exactly the same width, and the grid reflows cleanly. The Flexbox version is better when cards can have variable widths and you want them to use available space more fluidly.
The Alignment Difference
In Flexbox, you align items along the main axis (the direction you chose) and the cross axis (perpendicular to it). You cannot independently control a cell's position within an invisible grid of rows and columns.
In Grid, every item lives in a cell with both a row and a column position. You can place an item at row 2, column 3 explicitly, or let the browser auto-place it. Flexbox has no concept of cells — items just flow in the direction you specified.
Common Mistakes
Using Grid for simple centering: display: flex; align-items: center; justify-content: center is faster than setting up a grid for a single element. Flexbox wins on single-axis tasks.
Using Flexbox for full page layouts: Once you have more than two components that need to relate to each other positionally (header + sidebar + content + footer), Flexbox's lack of a second axis becomes a problem. Grid handles this with named areas.
Using Flexbox column as a substitute for Grid rows: flex-direction: column lets items stack vertically, but you lose the ability to align content across multiple columns simultaneously. If you are thinking about columns, switch to Grid.
Using Both Together
Grid and Flexbox are not mutually exclusive. The most common real-world pattern is Grid for the page-level layout, Flexbox inside each section:
- Grid positions the sidebar, header, and main content area
- Inside the navigation (which sits in the header area), Flexbox handles the logo + links + CTA button row
- Inside the main content area, a card grid uses Grid for column structure
- Inside each card, Flexbox handles the icon + text + button layout
This composition pattern — Grid for structure, Flexbox for components — is how most modern CSS frameworks (Tailwind, Bootstrap) work internally.
Quick Property Reference
| What you want | Flexbox | Grid |
|---|---|---|
| Set layout direction | flex-direction | grid-template-columns/rows |
| Space between items | gap or justify-content | gap |
| Align on cross axis | align-items | align-items |
| Place an item specifically | Not possible directly | grid-column / grid-row |
| Make items equal height | align-items: stretch | Default behavior |
| Responsive without media queries | flex-wrap: wrap + flex-basis | auto-fill + minmax() |
Build Flexbox Layouts Visually
Use our visual CSS Flexbox Generator to create flex containers, adjust alignment, and copy the generated CSS in seconds.