Most developers learn just enough Flexbox to center a div and just enough Grid to feel confused. Then they reach for a CSS framework. But Flexbox and Grid together handle every layout you will ever need — sidebars, card grids, holy grail layouts, responsive navigation — without a single framework dependency.
The One Rule: Grid for Layout, Flexbox for Alignment
- CSS Grid: Two-dimensional (rows AND columns). Use for page-level layout and component structure.
- Flexbox: One-dimensional (row OR column). Use for aligning items within a container.
They are not competitors. Use Grid for the overall page structure, then Flexbox inside each Grid cell for alignment.
Flexbox Essentials
/* The container controls how children behave */
.flex-container {
display: flex;
flex-direction: row; /* row | column | row-reverse | column-reverse */
justify-content: center; /* Main axis: start | center | end | space-between | space-around | space-evenly */
align-items: center; /* Cross axis: start | center | end | stretch | baseline */
gap: 1rem; /* Spacing between items */
flex-wrap: wrap; /* Allow wrapping to next line */
}
/* Children control their own sizing */
.flex-item {
flex: 1; /* Grow to fill available space */
/* flex: 1 is shorthand for: flex-grow: 1; flex-shrink: 1; flex-basis: 0; */
}
Common Flexbox Patterns
/* 1. Center anything (the classic) */
.center-everything {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* 2. Navigation bar */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.navbar-links {
display: flex;
gap: 1.5rem;
}
/* 3. Card footer pushed to bottom */
.card {
display: flex;
flex-direction: column;
height: 100%;
}
.card-body {
flex: 1; /* Takes all available space, pushes footer down */
}
.card-footer {
margin-top: auto; /* Alternative: push to bottom */
}
/* 4. Input with button */
.search-bar {
display: flex;
}
.search-bar input {
flex: 1; /* Input takes remaining space */
}
.search-bar button {
flex-shrink: 0; /* Button never shrinks */
}
CSS Grid Essentials
/* Define rows and columns */
.grid-container {
display: grid;
grid-template-columns: 250px 1fr 250px; /* sidebar | main | sidebar */
grid-template-rows: auto 1fr auto; /* header | content | footer */
gap: 1rem;
min-height: 100vh;
}
/* Place items by name (much clearer than line numbers) */
.grid-container {
grid-template-areas:
"header header header"
"left main right"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar-left { grid-area: left; }
.main-content { grid-area: main; }
.sidebar-right { grid-area: right; }
.footer { grid-area: footer; }
Responsive Grid Without Media Queries
/* Auto-fit: cards that wrap and fill available space */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
/* On wide screen: 3-4 columns
On tablet: 2 columns
On mobile: 1 column
ZERO media queries! */
/* Auto-fill vs auto-fit:
auto-fill: creates empty columns even with few items
auto-fit: collapses empty columns so items stretch */
/* Fixed minimum, flexible maximum */
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}
Common Grid Patterns
/* 1. Holy grail layout */
.page {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
min-height: 100vh;
}
/* Make it responsive with one media query */
@media (max-width: 768px) {
.page {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"nav"
"main"
"aside"
"footer";
}
}
/* 2. Dashboard layout */
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto;
gap: 1rem;
}
.widget-large {
grid-column: span 2;
grid-row: span 2;
}
.widget-wide {
grid-column: span 2;
}
/* 3. Masonry-like layout (with Grid) */
.masonry {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 10px; /* Small base row */
gap: 1rem;
}
.masonry-item-small { grid-row: span 20; }
.masonry-item-medium { grid-row: span 30; }
.masonry-item-large { grid-row: span 40; }
Grid + Flexbox Together
/* Grid for page layout, Flexbox inside each cell */
.app {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 60px 1fr;
grid-template-areas:
"sidebar header"
"sidebar main";
height: 100vh;
}
/* Header uses Flexbox for alignment */
.header {
grid-area: header;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2rem;
}
/* Main content uses Grid for card layout */
.main {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
padding: 2rem;
overflow-y: auto;
}
/* Each card uses Flexbox for internal layout */
.card {
display: flex;
flex-direction: column;
border-radius: 8px;
overflow: hidden;
}
.card-content { flex: 1; padding: 1rem; }
.card-actions {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
padding: 1rem;
}
Subgrid: Aligning Nested Grids
/* Parent grid */
.card-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
/* Child uses parent's grid lines for consistent alignment */
.card {
display: grid;
grid-template-rows: subgrid; /* Inherit parent's row tracks */
grid-row: span 3; /* Card occupies 3 rows */
}
/* Now all card titles, bodies, and footers align across cards
even when content lengths differ */
Decision Guide
| Use Case | Use | Why |
|---|---|---|
| Page layout (header/sidebar/main) | Grid | Two-dimensional, named areas |
| Card grid | Grid | auto-fit/minmax for responsive wrapping |
| Navigation links | Flexbox | One row of items with spacing |
| Center content | Flexbox | justify-content + align-items |
| Form layout | Grid | Label/input pairs in columns |
| Toolbar buttons | Flexbox | Single row, variable spacing |
| Dashboard widgets | Grid | Spanning rows/columns |
| Sticky footer | Flexbox or Grid | Both work well |
Key Takeaways
- Grid for two dimensions, Flexbox for one — this rule alone solves 90% of layout decisions
- Use grid-template-areas for readable, maintainable page layouts
- repeat(auto-fit, minmax(300px, 1fr)) creates responsive grids without media queries
- Combine Grid and Flexbox: Grid for structure, Flexbox for alignment within cells
- flex: 1 on a child makes it grow to fill available space — perfect for push-to-bottom patterns
- gap works in both Grid and Flexbox — no more margin hacks
- Subgrid aligns nested content across sibling elements — use it for card lists
- You probably do not need a CSS framework — Grid + Flexbox + custom properties handle everything
The secret to CSS layout is not memorizing properties — it is understanding the mental model. Grid thinks in tracks (rows and columns). Flexbox thinks in flow (main axis and cross axis). Once you internalize these two mental models, layout stops being a guessing game and becomes intentional design.