Overview
Flexbox and Grid solve different shapes of layout problem. Flexbox is one-dimensional: it distributes items along a single row or column, and each line sizes itself independently based on its content. Grid is two-dimensional: rows and columns are defined together as a single track system, so content can align across both axes at once. Neither replaced the other, Flexbox shipped first and remains the right tool for linear arrangements (navbars, button groups, form rows), while Grid is the right tool whenever rows and columns need to line up as a unit (page shells, card grids, dashboards).
Quick Reference
| Need | Reach for | Why |
|---|---|---|
| A row of nav links or buttons | Flexbox | One-dimensional, content-sized |
| A centered single item | Either | Both have simple centering (place-items: center / justify-content + align-items) |
| A page shell (header/sidebar/content/footer) | Grid | Explicit two-dimensional track structure |
| A responsive card grid | Grid (auto-fit/minmax) | Automatic column count without media queries |
| Equal-height columns that also wrap | Flexbox with flex-wrap | Content-driven wrapping along one axis |
Syntax
/* Flexbox: one-dimensional row, items grow/shrink to fill space */
.flex-row {
display: flex;
gap: 1rem;
align-items: center;
justify-content: space-between;
}
/* Grid: two-dimensional, explicit rows and columns */
.grid-shell {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
gap: 1rem;
}Examples
/* Responsive card grid with zero media queries */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.5rem;
}/* A toolbar: Flexbox is the right tool for a single row of controls */
.toolbar {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
align-items: center;
}Visual Diagram
Common Mistakes
- Reaching for nested Flexbox rows to fake a grid; this makes columns in different rows unable to align to each other, which Grid does natively.
- Using Grid for a simple single-row layout where Flexbox's content-driven sizing would be simpler and need less explicit configuration.
- Forgetting
gapworks in both Flexbox and Grid, no need for manual margin hacks between items. - Not using
minmax()withauto-fit/auto-fillfor responsive grids, and reaching for a media-query breakpoint per screen size instead.
Performance
- Both Grid and Flexbox are computed during the browser's layout pass; neither is inherently "faster," but deeply nested Flexbox rows used to fake grid alignment add extra layout nodes compared to a single Grid container achieving the same result.
- Changing
grid-template-columns/flex-basisvalues can trigger layout thrashing if done frequently via JavaScript, prefer CSS custom properties toggled by a class over direct inline style mutation in a loop.
Best Practices
- Default to Flexbox for one-dimensional arrangements (toolbars, nav bars, button groups, form rows).
- Default to Grid whenever rows and columns need to align together (page layouts, card grids, dashboards).
- Combine them: Grid for the outer structure, Flexbox for the contents of an individual grid area.
- Use
repeat(auto-fit, minmax(...))for responsive grids instead of hand-written breakpoints where the layout logic is genuinely just "as many columns as fit."