The Core Mental Model
The single most useful mental model: Flexbox is one-dimensional, Grid is two-dimensional.
- Flexbox controls layout along a single axis — either a row or a column.
- Grid controls layout across two axes simultaneously — rows and columns.
This isn't just a technicality. It fundamentally changes what each system is good at and how you should think when reaching for one.
When to Use Flexbox
Flexbox shines when you need to align or distribute items along a single axis and want the items themselves to control their own sizing.
Navigation bars
A classic Flexbox use case. You want items in a row, spaced evenly, with automatic wrapping on small screens:
.nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
Card button groups
When you have a group of buttons inside a card and want them aligned regardless of label length, Flexbox handles this perfectly with justify-content: flex-end or gap.
Centering content
The cleanest way to center an element both horizontally and vertically:
.centered {
display: flex;
align-items: center;
justify-content: center;
}
Component internals
Inside small UI components — icon + text combos, tags, badges — Flexbox keeps things clean and compact. It's ideal when you don't know the exact number of items in advance.
Try it live: Use StudioLimb's Flexbox Playground to experiment with all justify-content and align-items values visually.
When to Use Grid
Grid is the right tool when you're thinking about the entire layout at once — defining rows and columns first, then placing content into that structure.
Page-level layouts
Header, sidebar, main content, footer — this is Grid's native territory:
.page {
display: grid;
grid-template-columns: 260px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
header { grid-column: 1 / -1; }
sidebar { grid-row: 2; }
main { grid-column: 2; grid-row: 2; }
footer { grid-column: 1 / -1; }
Card grids
When you want a responsive grid of cards that automatically fills columns without media queries:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
Complex overlapping layouts
Grid allows elements to overlap via named areas or explicit row/column placement — something Flexbox cannot do without position: absolute.
Try it live: Build your layout visually with StudioLimb's CSS Grid Generator.
Can You Use Them Together?
Absolutely — and you often should. A common pattern: Grid defines the macro layout of the page, Flexbox handles the micro layout inside each component. There's no rule against nesting them.
Quick Decision Guide
| Scenario | Best Choice |
|---|---|
| Navigation bar | Flexbox |
| Page layout (header/sidebar/main) | Grid |
| Centering a single element | Flexbox |
| Responsive card gallery | Grid |
| Button group inside a card | Flexbox |
| Magazine-style editorial layout | Grid |
| Icon + label combinations | Flexbox |
| Dashboard with fixed sidebar | Grid |
The Honest Answer
In practice, experienced developers reach for Flexbox first because it's slightly simpler for most component-level work. When you catch yourself fighting Flexbox to control things on two axes — that's your signal to switch to Grid. Trust the friction.
Flexbox Deep Dive: flex-grow, flex-shrink, flex-basis
The shorthand flex: 1 is everywhere, but few developers understand exactly what it sets. It's shorthand for flex-grow: 1; flex-shrink: 1; flex-basis: 0%. Here's what each part actually does:
flex-grow
Determines how much of the remaining free space an item claims. If two items have flex-grow: 1 and flex-grow: 2 respectively, the second one grows twice as much as the first. If all items have flex-grow: 0 (the default), no item grows.
/* Sidebar + main content layout */
.sidebar { flex: 0 0 260px; } /* Don't grow, don't shrink, stay 260px */
.main { flex: 1; } /* Claim all remaining space */
flex-shrink
Controls how items shrink when the container is too small. Default is 1 (items shrink proportionally). Set to 0 to prevent an item from ever shrinking below its flex-basis:
/* Icon in a button that should never shrink */
.btn-icon {
flex-shrink: 0;
width: 20px;
height: 20px;
}
flex-basis
The ideal starting size of an item before free space is distributed. The difference between flex-basis: 0% and flex-basis: auto is subtle but important:
flex-basis: 0%— ignores the item's content size; distributes all space proportionally via flex-growflex-basis: auto— uses the item's content size as the starting point before distributing remaining space
Use flex: 1 (basis 0%) when you want all items to be exactly equal width. Use flex: 1 1 auto when you want items to start at their natural size and grow/shrink from there.
Grid Deep Dive: auto-fill vs auto-fit
Both create responsive grids without media queries, but they behave differently when there are fewer items than columns:
/* auto-fill: creates empty column tracks to fill the row */
.grid-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
/* auto-fit: collapses empty tracks, items stretch to fill */
.grid-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
If you have 2 items in a 4-column row: auto-fill leaves 2 empty columns (items stay at 200px wide); auto-fit collapses the empty columns and stretches the 2 items to fill the full width. For card grids, auto-fill is usually preferred — items maintain consistent widths.
Grid Template Areas: The Readable Layout Approach
Named grid areas let you define your layout visually in code. This is one of Grid's most underused and most powerful features:
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr 48px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
/* Responsive: stack on mobile */
@media (max-width: 768px) {
.page {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
}
The grid-template-areas string is a visual representation of your layout — you can literally see the structure in the CSS.
Common Flexbox and Grid Mistakes
1. Using Flexbox for a card gallery
Flex items wrap onto new lines but don't align to a grid — each row is independent. The result is cards with inconsistent widths on the last row. Use grid with auto-fill / auto-fit for any gallery or card grid.
2. Not setting explicit width on flex children
Flex items shrink to fit by default. If a child contains long text, it may shrink unexpectedly. Use min-width: 0 on flex children containing text to allow them to shrink below their content size and use overflow: hidden; text-overflow: ellipsis properly.
3. Nesting grids unnecessarily
Developers sometimes put a grid inside a grid to handle component-level alignment. In most cases, Flexbox inside a Grid cell is the cleaner approach — use Grid for the macro layout, Flexbox for the component internals.
4. Forgetting that gap works on both
Since 2021, gap works on Flexbox containers too (previously it was Grid-only). No more margin hacks on flex children to create spacing.
5. Using align-items vs align-content wrong
align-items aligns items within their row. align-content aligns the rows themselves within the container. If your container doesn't have a defined height or only has one row, align-content has no visible effect.
Frequently Asked Questions
Can I use Flexbox and Grid together?
Absolutely — and you should. The most common pattern is Grid for the outer page structure, Flexbox for component internals. A grid cell can itself be a flex container. There is no performance penalty for nesting them.
Is Grid harder to learn than Flexbox?
Grid has more properties and a steeper initial learning curve, but once you internalize the two-dimensional mental model it becomes intuitive. Start with grid-template-columns, gap, and auto-fill/minmax — those three get you 80% of the way there.
When should I use neither and just use normal block flow?
For single-column text content — articles, blog posts, documentation — normal block flow (the default) is often the right choice. Not every layout needs Flexbox or Grid. Reaching for a layout primitive when block flow works adds complexity without benefit.
Does CSS Grid replace Bootstrap's grid system?
Yes, for new projects. Native CSS Grid is more powerful, requires no classes or framework, and doesn't carry any JavaScript weight. Bootstrap's grid made sense before native Grid had broad browser support; that era is over.