What you'll learn
Quick Answer
Flexbox lays out items along one axis — a row or a column — and sizes them based on their content. Grid lays out in two dimensions at once, with rows and columns defined by the container. Use Flexbox for components such as navbars, button groups and card internals. Use Grid for page-level structure and anything needing alignment in both directions. They are complementary, and most real pages use Grid for the page and Flexbox inside the pieces.
One Dimension vs Two, and What That Means
The textbook answer is that Flexbox is one-dimensional and Grid is two-dimensional. That is correct but abstract, so here is what it means in practice.
Flexbox lays items along a single axis. You choose row or column, and items flow along it. If they wrap to a second line, each line is sized independently — there is no relationship between an item on line one and an item below it.
Grid defines rows and columns up front, and items are placed into that structure. A cell in column two of row one is aligned with the cell in column two of row three, because the column exists as a thing.
Flexbox with wrapping — lines are independent:
[ item ][ longer item ][ it ]
[ another ][ x ] ← no column alignment
Grid — columns exist:
[ item ][ longer ][ it ]
[ another ][ x ][ ] ← aligned in both directionsThe second framing that decides most real cases: Flexbox is content-first, Grid is layout-first. In Flexbox the items' own sizes shape the layout. In Grid the container declares the structure and the items fit into it.
So if you know the shape you want, that is Grid. If you want things to arrange themselves around their content, that is Flexbox.
What Flexbox Is Best For
Anything arranged along one line, where item sizes should respond to content.
/* Navbar: logo left, links right */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Centring — the most searched CSS question there is */
.center {
display: flex;
justify-content: center; /* main axis */
align-items: center; /* cross axis */
}
/* Card footer pinned to the bottom regardless of content height */
.card { display: flex; flex-direction: column; }
.card-body { flex: 1; } /* takes the leftover space */That last pattern is genuinely useful and hard with Grid — flex: 1 means "absorb the remaining space", which pushes anything after it to the end.
The flex shorthand is worth knowing properly. flex: 1 is flex-grow: 1; flex-shrink: 1; flex-basis: 0. The flex-basis: 0 is why flex: 1 on several items makes them equal width regardless of content, while flex-grow: 1 alone distributes only the leftover space and leaves items unequal.
Other natural Flexbox uses: button groups, tag lists, form rows, toolbars, and the inside of a card. Note the common thread — these are components, not pages.
What Grid Is Best For
Page structure and anything needing alignment in both directions.
/* Page layout, described declaratively */
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }Named areas make the layout readable at a glance, which no Flexbox equivalent achieves.
The single most useful Grid line is a responsive card layout with no media queries at all:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}Cards are at least 250px wide, share space equally, and the number per row changes with the viewport automatically. Doing this with Flexbox requires media queries and percentage widths, and the last row never looks right.
fr is Grid's own unit meaning a fraction of the free space — 1fr 2fr splits it one third and two thirds. It handles gaps correctly, unlike percentages.
Other good Grid cases: dashboards, image galleries, forms with aligned labels, and any table-like arrangement that is not tabular data.
Using Both Together
These are not competitors. Real pages use Grid for the page skeleton and Flexbox inside the pieces.
/* Grid positions the major regions */
.layout { display: grid; grid-template-columns: 250px 1fr; }
/* Flexbox arranges what is inside one region */
.header { display: flex; justify-content: space-between; align-items: center; }
/* Grid again for the card collection */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
/* Flexbox again inside a single card */
.card { display: flex; flex-direction: column; }The rule that resolves most decisions: ask whether you are arranging things in one direction or two. Then ask whether the container should dictate the structure or the content should. One direction and content-driven means Flexbox; two directions or structure-driven means Grid.
Two properties they share, which is worth knowing because they are frequently attributed to only one:
gapworks in both, and is far better than margins for spacing — no negative margin hacks and no trailing space on the last item.- Alignment properties —
justify-content,align-items— exist in both, though in Grid they align tracks rather than items along an axis.
Gotchas in Both
Flexbox: items shrink below their content by default. A long word or a wide element can overflow because min-width defaults to auto but flex items get an implicit minimum. The fix is explicit:
.flex-item { min-width: 0; } /* allows shrinking and text truncation */This is the reason text-overflow: ellipsis mysteriously fails inside a flex container.
Flexbox: flex-grow alone does not equalise widths. Without flex-basis: 0, items keep their content-based size and only share the leftover space. Use flex: 1.
Grid: 1fr also has a minimum of auto. A grid column can refuse to shrink below its content, causing overflow. Use minmax(0, 1fr) when the content might be wide.
Grid: only direct children are grid items. Grandchildren are laid out by their own parent, which surprises people expecting the whole subtree to participate. Subgrid addresses this and is now widely supported.
Both: the gap property does not collapse. Unlike margins, gaps never merge — usually what you want, but different from the box model behaviour people expect.
Browser support is a non-issue for both in 2026. Neither needs a fallback, and using Flexbox purely for compatibility reasons is no longer a valid argument.
