HTML5 Please

CSS Grid vs Flexbox: Which One and When

CSS Grid vs Flexbox: Which One and When

The question gets asked as though one of them won. It did not. Grid and Flexbox solve different problems, they were designed to sit side by side, and almost every real page uses both. What people actually want to know is which one to reach for in front of a given box, so here is the rule that decides it, followed by the cases where each shines and the mistakes that eat an afternoon.

The rule in one line

Flexbox lays out content along one axis. Grid lays out content along two axes at once.

That is the whole distinction, and it is more useful than it sounds. If you are arranging things in a row, or in a column, and you mostly want them to space themselves out sensibly, that is Flexbox. If you need rows and columns to line up with each other, so that the second item in row one sits directly above the second item in row two, that is Grid.

There is a second way to say it that clicks for some people. Flexbox is content out: the items tell the layout how big they want to be, and the container distributes what is left. Grid is layout in: you define the tracks first, then place content into them. When the sizing should come from the content, reach for Flexbox. When the structure should come first, reach for Grid.

Where Flexbox wins

Anything that is essentially a line of things. A navigation bar, a toolbar, a row of buttons, the meta line under an article title, the inside of a card where an icon sits next to a label. These are one dimensional by nature and Flexbox handles them with almost no code.

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
}
.toolbar .spacer { margin-left: auto; }

That margin-left: auto trick is the reason Flexbox stays in the toolkit. One property pushes everything after it to the far end, and it keeps working when items are added or removed. Grid can do the same thing but you have to think about tracks to get there.

Flexbox is also the right answer when items should wrap naturally and you genuinely do not care whether the last row lines up. A tag list is the classic example: tags are different widths, they wrap when they run out of room, and nobody expects a tidy column edge.

Where Grid wins

Page level layout, and any gallery where alignment across rows matters. The moment you catch yourself fighting the last row of a wrapped Flexbox container, you wanted Grid.

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px;
}

Those three lines give you a responsive card gallery with no media queries at all. Columns are at least 240 pixels wide, they share the leftover space equally, and the count adapts to the container. Doing the same in Flexbox means percentage widths, negative margins on the last row, and a comment apologising for it.

Grid is also the only sane option for two other jobs. The first is aligning things across separate components, which is what subgrid exists for: a nested grid can inherit the parent tracks so that headings and buttons in adjacent cards line up even when the text lengths differ. The second is deliberate overlap. Place two items in the same grid area and they stack, which is far more predictable than absolute positioning for hero sections and image captions.

They are meant to be combined

The layout most sites end up with is Grid for the page skeleton and Flexbox inside the components. That is not a compromise, it is the intended design.

.page { display: grid; grid-template-columns: 1fr min(70ch, 100%) 1fr; }
.page > * { grid-column: 2; }
.card { display: flex; flex-direction: column; gap: 10px; }
.card footer { margin-top: auto; }

The margin-top: auto on the card footer is worth stealing. It pins the footer to the bottom of the card regardless of how much text is above it, which is exactly what makes a row of cards look deliberate rather than ragged.

Things that trip people up

  • Fighting the last row in a wrapped flex container. If the final row of items stretching wide bothers you, you did not want Flexbox. Switch to Grid with auto-fit and the problem disappears.
  • Reaching for Grid on a nav bar. It works, but you will write more code and gain nothing. One axis means Flexbox.
  • Forgetting that gap works in both. It has for years. If you still see margins between flex items in a codebase, that is a leftover from before support landed and it is safe to modernise.
  • Percentage widths inside Flexbox. flex-basis with min-width: 0 solves more sizing problems than percentages do, especially when the content includes long words or code.
  • auto-fill when you meant auto-fit. With auto-fill empty tracks are kept, so a single card can end up hugging the left edge of a wide container. auto-fit collapses them.
  • Nesting grids where subgrid belongs. A nested independent grid cannot align with its parent's tracks. Subgrid can.

Support in 2026

Neither is a question any more. Flexbox and Grid have been safe across every browser people actually use for years, and gap in Flexbox has been widely available since 2021. The one worth checking against your own audience is subgrid, which arrived later and is now broadly supported but still the thing most likely to bite an older device. Our readiness pages for grids and flexbox carry the details, and the MDN guide to grid layout is the reference worth bookmarking.

So which one

Ask what the box is doing. One line of things that size themselves: Flexbox. A structure with rows and columns that must line up: Grid. Everything else is a matter of which of those two the case resembles more, and when you truly cannot decide, it is usually because the component wants Grid on the outside and Flexbox on the inside.

One last thing worth adding to the mix. Both of these respond to the page, not to the component's own space, which is a different problem entirely and the reason container queries matter. Grid and Flexbox decide the shape, container queries decide when that shape changes. Used together they replace most of the media query soup that older stylesheets are built from.