Flexbox vs Grid: which CSS layout should you choose?
Flexbox and CSS Grid are two layout systems built into the browser. Flexbox is one-dimensional (a row or a column); Grid is two-dimensional (rows and columns at once). Learn how each one works, when to reach for it, and how to combine them.
On this page
Flexbox and CSS Grid are both built into the browser, both designed to replace the float-and-clear hacks that web developers lived with for a decade, and both are excellent at what they do. They are not interchangeable: each one solves a different problem. Flexbox lays things out in a single line — a row or a column. Grid lays things out in two dimensions at once — rows and columns together. Picking the right one starts with that distinction, and the rest of this guide shows you how to apply it.
The MDN relationship guide puts the rule bluntly: "The basic difference between CSS grid layout and CSS flexbox layout is that flexbox was designed for layout in one dimension - either a row or a column. Grid was designed for two-dimensional layout - rows, and columns at the same time." If you can already do the job in one axis, flexbox is the lighter tool. If your layout needs both axes to stay aligned, grid is the only one of the two that can do it cleanly.
What Flexbox is
Flexbox is the layout system you use for a single line of items in a row or a column. You turn any element into a flex container by setting display: flex (or display: inline-flex), and its direct children become flex items that the browser arranges along a main axis you control with the flex-direction property.
The four flex-direction values give you the four possible flows:
row— items line up horizontally, left to right in a left-to-right language.row-reverse— same asrowbut the start and end lines are swapped.column— items stack vertically, top to bottom.column-reverse— same ascolumnbut the start and end lines are swapped.
The key insight from the MDN flexbox guide is that flexbox has two axes: the main axis (set by flex-direction) and a cross axis that runs perpendicular to it. Every flex property you write either moves things along one of these axes, or grows and shrinks items along them. The two most useful flex-item properties are the flex shorthand and the alignment properties.
A typical flexbox row with three items that share the available space is two lines of CSS:
.nav {
display: flex;
}
.nav > a {
flex: 1; /* flex: 1 1 0 — grow, shrink, zero base */
}
The flex shorthand expands to flex-grow, flex-shrink, and flex-basis in that order. Writing flex: 1 is equivalent to flex: 1 1 0, which means the items start at zero size and grow equally to fill the available space. Writing flex: 2 1 0 would give that item twice the share of the space.
Flexbox is also the right tool for centering an item inside its parent, which is famously awkward with earlier CSS. The web.dev flexbox guide walks through this exact pattern: justify-content aligns along the main axis, align-items aligns along the cross axis, and combining center on both gives you a centered item in any flex container.
The reason flexbox stays useful even when grid exists is that most layout work on a page is one-dimensional. A navigation bar, a toolbar, a row of action buttons, a list of cards that wraps to the next line, a footer with three columns of links — all of these are single-line layouts, and flexbox is the simplest, most predictable tool for each one.
What Grid is
CSS Grid is the layout system for two-dimensional layouts: when items need to line up in rows and columns at the same time. You turn any element into a grid container with display: grid (or display: inline-grid), and its direct children become grid items that the browser places into a grid you define.
The grid is defined with two properties: grid-template-rows and grid-template-columns. Each one lists the sizes of the rows and columns. The fr unit — short for "fraction" — is a grid-only length that represents a share of the available space in the container:
.page {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* three columns: 25% / 50% / 25% */
gap: 16px;
}
This produces a page with a left sidebar, a main column twice as wide, and a right sidebar, with a 16-pixel gap between every track. The two outer columns are equal because they both have 1fr; the middle column is twice as wide because it has 2fr. If you resize the browser, all three columns resize proportionally without any media query.
The repeat() function and minmax() function take this further. A common pattern is a fluid card grid that always keeps the cards above a minimum readable width:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 16px;
}
The auto-fit keyword asks the browser to fit as many 250-pixel-minimum column tracks as it can into the container, and minmax(250px, 1fr) says each track can grow beyond 250 pixels to share leftover space. On a wide screen you might see four cards per row; on a tablet, three; on a phone, one. All from those two functions, with no media query.
The other defining feature of grid is that you can place items precisely. Grid lines are numbered from the start edge, and you can tell an item which lines to start and end at:
.header { grid-column: 1 / 3; grid-row: 1; } /* spans columns 1 to 2, row 1 */
.sidebar { grid-column: 1; grid-row: 2; }
.main { grid-column: 2; grid-row: 2; }
The MDN grid basics guide shows the full longhand (grid-column-start, grid-column-end, grid-row-start, grid-row-end) as well as the shorthand. Either form works; the shorthand is what you will see in real code.
Grid is the right tool for whole-page layouts, dashboard layouts, image galleries, form layouts where labels and inputs need to line up across rows, and any other case where the relationship between items in both dimensions matters.
The key differences
| Aspect | Flexbox | Grid |
|---|---|---|
| Dimensions | One (row or column) | Two (rows and columns at once) |
| Mental model | Content-out — items decide how much space they take | Layout-in — you create the layout, then items fill it |
| Main axis | Set by flex-direction (row, column, two reverse variants) |
Set implicitly by your row + column definition |
| Distribution of free space | flex-grow / flex-shrink / flex-basis per item |
fr unit on tracks, auto-fit / auto-fill on track lists |
| Alignment | justify-content (main), align-items + align-self (cross) |
Same box-alignment properties, applied to grid areas |
| Overlapping items | Awkward; usually not the goal | Native — items can share cells with z-index ordering |
| Wrapping | flex-wrap: wrap creates independent flex lines |
The whole grid is one strict 2D structure (wrap is the default) |
| Best for | Navigation bars, toolbars, single rows, evenly-spaced items | Page layouts, card grids, dashboards, anything needing both axes |
| Source of truth | The w3.org CSS Flexbox Box Layout Module Level 1 spec | The w3.org CSS Grid Layout Module Level 1 spec |
When Flexbox is the better choice
Reach for flexbox when the layout is genuinely one-dimensional, or when the items themselves should drive the sizing:
- Navigation bars and toolbars — a row of links or buttons that should share the available width, or right-align a single action button. Flexbox is the simplest, most readable way to express this.
- Evenly spaced groups of items — tags, chips, action menus, where you want them distributed with
justify-content: space-betweenorspace-around. The MDNjustify-contentreference lists every value (flex-start,flex-end,center,space-between,space-around,space-evenly, and a few writing-mode-aware ones). - Centering a single element in its parent — combining
justify-content: centerandalign-items: centeron a flex container is the cleanest one-liner. - Lists that wrap to a new line gracefully — setting
flex-wrap: wrapand giving each item aflex-basisproduces a row that reflows on narrow screens without any media query. - Component internals — the inside of a card, the inside of a button, the inside of a form field. Flexbox rarely surprises you when the scope is one component.
If you are writing flexbox and find yourself setting width on a flex item to make it line up with the items above it, you are probably fighting the one-dimensional model. That is a strong signal to switch to grid.
When Grid is the better choice
Reach for grid when the layout needs both axes, or when you are designing a layout in advance and want items to fall into it:
- Whole-page layouts — header, sidebar, main, footer. The MDN relationship guide shows this exact pattern using
grid-template-areaswith named regions. It is the most readable CSS you can write for a page-level layout. - Card grids and image galleries — the
repeat(auto-fit, minmax(250px, 1fr))pattern from earlier handles a fluid grid with no media queries and no JavaScript. - Dashboards and admin panels — multiple panels that need to align both horizontally and vertically. Grid's
align-itemsandjustify-itemskeep every cell of the dashboard aligned without you having to track heights. - Forms with aligned labels and inputs — grid is the only way to make a column of labels line up with the inputs across every row, because that is a two-axis problem.
- Overlapping content — cards with badges that overlay the top-right corner, image captions that sit on top of a hero image. Grid's
grid-column/grid-rowplacement andz-indexmake overlapping items clean.
The MDN relationship guide also describes grid as "layout-in" — you create the layout first (the rows, the columns, the gaps), and then items slot into it. This is the opposite of flexbox's "content-out" model, where items ask for space and the container distributes it. Picking the right mental model is half the battle.
They work well together
You do not have to pick one and use it everywhere. The MDN relationship guide is explicit that grid is designed to be part of a complete system that includes flexbox. A typical real page uses grid for the page-level skeleton and flexbox for the navigation bar, the toolbar, the inside of every card, and every other one-dimensional component inside the grid cells. Treat them as two complementary layout systems, not two competitors.
A common pattern is a grid for the page skeleton, and a flexbox for the page header:
.page {
display: grid;
grid-template-rows: auto 1fr auto; /* header / main / footer */
min-height: 100vh;
}
.page > header {
display: flex;
justify-content: space-between;
align-items: center;
}
The outer grid makes the footer stick to the bottom of the viewport on short pages. The inner flexbox lays out the logo on the left and the navigation links on the right. Neither layout system was used for something the other does better.
FAQ
Can I use Flexbox and Grid on the same page?
Yes, and you usually should. Grid is the right tool for the page-level skeleton (the rows and columns that define where the major regions sit) and flexbox is the right tool for one-dimensional components inside those regions (the navigation bar, the toolbar, the contents of a card, the row of action buttons). The MDN relationship guide describes them as complementary parts of the same layout system, not alternatives. Most real-world designs use both.
Which is better for responsive design?
Neither is "better" — they solve different problems responsively. A flex container with flex-wrap: wrap reflows items to new lines as the container narrows, which is great for navbars and tag lists. A grid container with repeat(auto-fit, minmax(250px, 1fr)) keeps cards in a strict grid while still reflowing the number of columns. For page-level layouts that need to align in both dimensions, grid is the only realistic choice. For one-dimensional rows, flexbox usually needs fewer properties to express the same behavior.
When should I use Grid over Flexbox?
The MDN rule is the cleanest test: if you only need to control the layout by row or column, use flexbox; if you need to control it by row and column, use grid. Concrete signals to switch from flexbox to grid: you find yourself setting width on flex items to make them line up across rows, you need items to overlap, or you are building any kind of dashboard, card grid, or form layout.
Does Grid replace Flexbox?
No. Grid was added to CSS later, and for a moment the narrative was that grid was the modern replacement for flexbox. That turned out to be wrong. Flexbox is still the right tool for one-dimensional layouts, and the two systems now share most of their alignment properties through the CSS Box Alignment module. The web.dev flexbox guide and the MDN relationship guide both describe them as partners, not competitors.
Verdict
Pick flexbox for one-dimensional layouts (a row, a column, a wrapping list) and pick grid for two-dimensional layouts (a page, a card grid, a dashboard). If you find yourself disabling the flexibility of flexbox to force items into a grid shape, you want grid. If you find yourself creating a one-row grid to lay out a navigation bar, you want flexbox. Use them together: grid for the page skeleton, flexbox for the components inside.
Sources
- MDN — Basic concepts of flexbox (developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox
- CC-BY-SA 2.5+
- MDN contributors)
- MDN — Basic concepts of grid layout (developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Basic_Concepts_of_Grid_Layout
- CC-BY-SA 2.5+
- MDN contributors)
- MDN — Relationship of grid layout to other layout methods (developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Relationship_of_grid_layout_with_other_layout_methods
- CC-BY-SA 2.5+
- MDN contributors)
- web.dev — Learn CSS: Flexbox (web.dev/learn/css/flexbox
- CC BY 4.0 content / Apache 2.0 code
- Rachel Andrew)
Share this guide
Related guides
- What is web accessibility (a11y)? WCAG principles and practical techniques
Web accessibility (a11y) means designing sites that anyone can use, regardless of ability. This guide explains the four WCAG principles — perceivable, operable, understandable, robust — and practical techniques: semantic HTML, keyboard navigation, alt text, and color contrast.
- What is responsive web design? How it works (media queries, fluid grids, images)
Responsive web design (RWD) makes pages render well on every screen size. Learn how media queries, fluid grids, fluid images, and the viewport meta tag work together.
- What is CSS Specificity? Selectors, Specificity, and the Cascade Explained
CSS specificity is the algorithm browsers use to pick which CSS rule wins when two declarations target the same element and property. This guide explains selectors, specificity calculation, the cascade, and inheritance — with practical examples.