CSS Grid vs Flexbox
Use Grid when things must line up in rows and columns, and Flexbox when items flow along one line and should size to their content. Grid is layout first: the container sets the tracks. Flexbox is content first: the items set their size.
Most real pages use both: Grid for the page and card grids, Flexbox inside the pieces. The demo below shows the difference that decides most cases.
See the difference
Same seven items, same minimum width of 140px, same gap. Drag the corner of the box to change its width and watch the last row. Flexbox stretches whatever is left over to fill the line. Grid keeps every column the same width, so the last row lines up with the rows above it.
Flexbox · flex-wrap
Grid · auto-fill
.row {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.row > * { flex: 1 1 140px; } .row {
display: grid;
grid-template-columns:
repeat(auto-fill, minmax(140px, 1fr));
gap: 8px;
} Side by side
| CSS Grid | Flexbox | |
|---|---|---|
| Dimensions | Two: rows and columns together. | One: a row or a column. Wrapped lines are independent of each other. |
| Who sets the size | The container. You define tracks and items fill them. | The items. Each sizes from its content, then the container shares out space. |
| Alignment across rows | Automatic. Column 2 is the same width in every row. | None. Each wrapped line is laid out on its own. |
| Overlapping items | Yes, place two items in the same cells. | No, not without absolute positioning or negative margins. |
| Placing items anywhere | Yes, by line number or named area, independent of source order. | Only reorder along the line with order. |
| Gap | Yes. | Yes. Supported in every current browser. |
| Best for | Page layouts, card grids, dashboards, forms with label columns. | Navbars, toolbars, button groups, tags, centring one thing. |
The real difference: layout in, or content out
"One dimension versus two" is the usual answer, and it is true, but the more useful way to decide is to ask who should decide the sizes.
With Grid, the container decides. You declare the tracks first
(240px 1fr, repeat(3, 1fr)) and the content is placed into them.
A long word in one card can still widen its column, but the whole column widens with it,
so every row stays lined up.
With Flexbox, the items decide. Each one starts from its content size, then the container shares out whatever space is left, or takes it away. A longer label makes a wider button. That is exactly right for a toolbar, and exactly wrong for a grid of cards.
Use Grid for
- Page layouts. Header, sidebar, content and footer are regions, and grid-template-areas lets you draw them.
- Card grids. Columns that line up in every row, with no orphaned last row.
- Dashboards. Panels of different sizes that still share edges.
- Forms with a label column.
grid-template-columns: max-content 1frlines every label up without fixed widths. - Anything that overlaps. Text on an image, a badge on a card.
/* Grid: the page decides the regions,
content is placed into them. */
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"nav main"
"footer footer";
min-height: 100dvh;
} The CSS grid generator draws this kind of layout for you at every breakpoint and writes the media queries.
Use Flexbox for
- Navbars and toolbars. Items sized to their text, one pushed to the end.
- Button groups and tags. An unknown number of items of different widths.
- Centring one thing.
display: flex; justify-content: center; align-items: center, thoughdisplay: grid; place-items: centerdoes the same in one line. - Card internals. A footer with a price on the left and a button on the right.
- Media objects. An avatar next to text that should take the rest of the width.
/* Flexbox: items size to their content,
the last one is pushed to the end. */
.nav {
display: flex;
align-items: center;
gap: 16px;
}
.nav .account { margin-left: auto; } The CSS Flexbox generator shows every flex property on a live preview, including the axis swap that trips everyone up.
Use both
This is the normal case, not a compromise. Any grid item can be a flex container, and any flex item can be a grid. A typical page:
.page { display: grid; grid-template-columns: 240px 1fr; }
.header { display: flex; align-items: center; gap: 16px; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.card-footer { display: flex; justify-content: space-between; } When nested content has to line up across separate cards, such as titles, prices and buttons all at the same height, neither nested flex nor nested grid can do it alone. That is what subgrid is for; the CSS subgrid generator builds it.
Common mistakes
Faking a grid with Flexbox. Percentage widths minus the gap, fixed with
calc(), adjusted at every breakpoint. If you are writing that, you wanted
Grid:
/* Flexbox pretending to be a grid */
.cards > * { width: calc(33.333% - 16px); }
/* What it wanted to be */
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
} Forcing a toolbar into Grid. Giving every button an equal
1fr column makes short labels waste space and long ones wrap. A row of
content-sized items is Flexbox's job.
Reordering visually and forgetting the DOM. Both Grid placement and flex
order move things on screen without moving them in the HTML. Keyboard and
screen-reader users follow the HTML, so the tab order can jump around.
Forgetting min-width: 0. Flex items and 1fr grid
tracks both refuse to shrink below their content by default. In a flex item set
min-width: 0; in a grid use minmax(0, 1fr), as covered in the
grid-template-columns guide.
Grid layouts to start from
Frequently asked questions
What is the difference between CSS Grid and Flexbox?
Is CSS Grid better than Flexbox?
Can I use Grid and Flexbox together?
Should I use Grid or Flexbox for a navbar?
margin-left: auto. That is exactly what Flexbox does. Grid is only worth it if the navbar has fixed regions, such as a logo, a centred menu and actions.Should I use Grid or Flexbox for a card layout?
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)) gives equal columns that line up in every row and reflow without media queries. With Flexbox, the last row stretches or leaves gaps depending on how many cards are left over.Can Flexbox do two-dimensional layouts?
flex-wrap makes several lines, but each line is laid out on its own, so items in different lines do not line up in columns. When you need that, you need Grid.