The Mental Model: One Axis vs Two
The most important thing to understand about CSS layout is that Flexbox and Grid are designed for different problems. Flexbox is one-dimensional — it places items along a single row or column, and the content drives the sizing. Grid is two-dimensional — it defines rows and columns simultaneously, and you can place items precisely at any intersection.
Think of it this way: if you are arranging items in a row or column where the number of items might change and you want them to distribute naturally — use Flexbox. If you are defining a layout structure with explicit rows and columns that items snap into — use Grid. In practice, most real UIs use both: Grid for the outer page structure, Flexbox for the internals of each component.
/* Grid controls the page macro-layout */
.app {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr auto;
min-height: 100vh;
}
/* Flexbox controls component micro-layout */
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.card {
display: flex;
flex-direction: column;
gap: 12px;
}
When to Use Flexbox
Flexbox is the right choice for any layout where items flow along a single axis and content drives sizing. Its real strength is distributing space and aligning items when you do not know their exact dimensions:
/* Navigation bar */
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 64px;
}
/* Responsive wrapping card row */
.cards {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card { flex: 1 1 280px; } /* grow, shrink, min-width */
/* Perfect centring */
.hero {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
/* Sticky footer with flex column */
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main { flex: 1; } /* pushes footer to bottom */
Use Flexbox for: navigation bars, button groups, toolbars, card content internals (title + body + footer stacked), tag/chip lists, any centring task, sidebar + content pairs where content should fill remaining space.
When to Use CSS Grid
Grid is the right choice when you need simultaneous control over rows and columns — when the layout definition should be independent of the content order:
/* Two-column page with header and footer */
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr auto;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
/* Auto-fill card grid */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
/* Dashboard with spanning items */
.dashboard {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.feature-card { grid-column: span 2; }
Use Grid for: page layouts, dashboard grids, magazine-style multi-column layouts, forms with aligned labels, any layout where items need to span multiple tracks, layouts where track definition should be separate from item sizing.
Combining Grid and Flexbox
The most powerful CSS layouts use both systems at different levels of the component hierarchy. There is no conflict — Grid and Flexbox operate on different elements and complement each other perfectly:
/* Outer page structure: Grid */
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr;
}
/* Navbar (Grid item): Flexbox internally */
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
}
/* Main content (Grid item): Grid for cards */
.content {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
padding: 24px;
}
/* Each card (Grid item): Flexbox internally */
.card {
display: flex;
flex-direction: column;
gap: 12px;
}
.card-body { flex: 1; }
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
Common Layout Patterns
Holy Grail Layout
The classic three-column layout with a full-width header and footer — traditionally one of the hardest patterns in CSS, now trivial with Grid:
.holy-grail {
display: grid;
grid-template:
"header header header" auto
"nav main aside" 1fr
"footer footer footer" auto
/ 200px 1fr 200px;
min-height: 100vh;
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
Responsive Without Media Queries
The auto-fill and minmax() combination creates truly responsive layouts that reflow at any breakpoint without writing a single media query:
/* Cards that auto-fit from 1 to N columns */
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
/* At 600px wide: 2 columns
At 900px wide: 3 columns
At 1200px wide: 4 columns
No media queries needed */
/* Flexbox wrapping equivalent */
.cards-flex {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card-flex { flex: 1 1 280px; }
Sidebar Layout with Flexible Content
/* Fixed sidebar, flexible content */
.layout {
display: grid;
grid-template-columns: 260px 1fr;
gap: 24px;
min-height: 100vh;
}
/* Collapse sidebar on mobile */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
}
.sidebar { display: none; }
}
Quick Decision Table
| Pattern | Use | Reason |
|---|---|---|
| Page layout with sidebar | Grid | Both rows and columns matter |
| Navigation bar | Flexbox | Single row, content-driven |
| Card grid | Grid | Explicit column tracks |
| Card internals | Flexbox | Column: title, body, footer |
| Sticky footer | Flexbox (column) | Simple flex: 1 on main |
| Modal overlay | Grid place-items or Flexbox | Both work equally |
| Form labels + inputs | Grid | Aligned across rows |
| Button group | Flexbox | Single row with gap |
Build complete layouts with our CSS tools
Flexbox Generator, Grid Generator, Border Radius, and Button Generator — all free, all instant.
Open Flexbox Generator →