Suggest an editImprove this articleRefine the answer for “flexbox vs CSS grid comparison”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Flexbox** is for one-dimensional layouts (a row or a column). **CSS Grid** is for two-dimensional layouts (rows and columns together). ```css /* Flexbox: one axis */ .nav { display: flex; justify-content: space-between; align-items: center; } /* Grid: two axes */ .layout { display: grid; grid-template-columns: 240px 1fr; } ``` **Decision rule:** Flexbox for components and 1D flows; Grid for page structure and 2D layouts.Shown above the full answer for quick recall.Answer (EN)Image**Flexbox** handles one-dimensional layouts (a single row or column); **CSS Grid** handles two-dimensional layouts (rows and columns at the same time). ## Theory ### TL;DR - Flexbox = a single bus aisle: items flow along one axis and shrink or grow to fill space - Grid = a city block: you define streets AND avenues, items sit at intersections - Main difference: Flexbox distributes space along one axis; Grid controls both axes at once - 1D layout (navbar, button group, card row)? Flexbox. Full page or dashboard? Grid - They combine well: Grid for the page shell, Flexbox inside each cell ### Quick example Same visual output, different levels of control: ```html <!-- Flexbox: items flow along main axis --> <div class="flex-row"> <div class="item">Nav</div> <div class="item">Logo</div> <div class="item">Login</div> </div> <!-- Grid: tracks defined upfront --> <div class="grid-layout"> <header>Header</header> <aside>Sidebar</aside> <main>Content</main> </div> ``` ```css /* Flexbox: one axis, space distributed between items */ .flex-row { display: flex; justify-content: space-between; align-items: center; } /* Grid: two axes, areas named explicitly */ .grid-layout { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: 60px auto; grid-template-areas: "header header" "sidebar content"; } ``` Flexbox doesn't know about rows. Grid doesn't care about content flow. That gap is where the real decision lives. ### Key difference Flexbox starts with content and distributes space around it. Items grow, shrink, and wrap, but always along one axis. Grid starts with structure: you define tracks first, then items fill them. That means Grid lets items span multiple rows and columns independently, while Flexbox items always follow the sequence. Nesting a Flexbox inside a Grid cell is common and natural - that combination covers most real-world layouts. ### When to use - Navbar with logo and menu links: Flexbox (`justify-content: space-between`) - Card row where all cards need equal height: Flexbox (`align-items: stretch`) - Page layout with header, sidebar, content, and footer: Grid - Dashboard with asymmetric panels of different sizes: Grid (`grid-template-areas`) - Centering a single element: both work (`display: flex; place-items: center` or `display: grid; place-items: center`) - Gallery where some items span multiple columns: Grid (`grid-column: span 2`) - Component inside a Grid cell, like a button group in a nav area: Flexbox ### Comparison table | Aspect | Flexbox | CSS Grid | |---|---|---| | Dimensions | 1D (row or column) | 2D (rows and columns) | | Primary strength | Space distribution along one axis | Explicit item placement and spanning | | Container behavior | Items flex to fill available space | Tracks are defined first, items fill them | | Item control | `flex-grow`, `flex-shrink`, `flex-basis`, `order` | `grid-area`, `grid-column`, `grid-row`, `place-self` | | Alignment | `justify-content`, `align-items`, `align-self` | `justify-items`, `align-items`, `place-items`, `place-content` | | Overlapping items | Not straightforward | Native support via shared grid area | | Browser support | IE10+, full modern support | IE11 partial; subgrid since Chrome 117 | | When to use | Navbars, button groups, card rows, centering | Page layouts, dashboards, galleries, print grids | ### How the browser handles this When the browser parses `display: flex`, it creates a flex formatting context. It calculates a hypothetical size for each item using `flex-basis`, then distributes leftover space by `flex-grow` factors. Line wrapping only happens when `flex-wrap: wrap` is set. `display: grid` creates a grid formatting context. The browser builds a track map from `grid-template-columns` and `grid-template-rows`, then places items either via explicit `grid-area` declarations or through the auto-placement algorithm. Grid track sizes are resolved once upfront; Flexbox recalculates on each reflow. For large lists (1000+ items), Flexbox tends to be faster because line caching is simpler than grid track resolution. ### Common mistakes **Mistake 1: Using `flex-direction: column` for a sidebar + main layout** ```css /* Wrong: flex-direction column just stacks items top to bottom */ .layout { display: flex; flex-direction: column; } /* Fix: Grid creates an actual side-by-side structure */ .layout { display: grid; grid-template-areas: "sidebar main"; grid-template-columns: 240px 1fr; } ``` This is the most common layout mistake I see in code reviews. Developers who know Flexbox well reach for `flex-direction: column` when they need columns side by side, and it just stacks vertically instead. **Mistake 2: `align-items: center` on Grid for full centering** ```css /* Wrong: only centers on cross-axis per track, not both axes */ .grid { display: grid; align-items: center; } /* Fix: centers both the block and inline axes */ .grid { display: grid; place-items: center; } ``` `align-items` handles the block axis. `justify-items` handles the inline axis. `place-items` is the shorthand for both, and it's what you actually want for true centering. **Mistake 3: `justify-content: space-between` with items of unequal width** ```css /* Looks uneven when item widths differ */ .nav { display: flex; justify-content: space-between; } /* Fix: gap gives predictable, consistent spacing */ .nav { display: flex; gap: 1rem; } ``` `space-between` distributes free space between items based on available room. When items have different widths, the gaps look inconsistent. `gap` applies the same spacing regardless of item size, and it doesn't bleed onto outer edges after wrapping. **Mistake 4: Missing `min-height: 0` on flex children in a column layout** ```css /* Item refuses to shrink, overflows the parent */ .sidebar-item { display: flex; flex-direction: column; /* Missing: min-height: 0 */ } /* Fix */ .sidebar-item { display: flex; flex-direction: column; min-height: 0; /* Allows shrinking below content size */ overflow: auto; } ``` Flex items default to `min-height: auto`, which prevents shrinking below content size. In column layouts this causes overflow. `min-height: 0` removes that restriction. **Mistake 5: Subgrid without matching parent tracks (Chrome 117+)** ```css /* Parent defines only two columns */ .grid-parent { display: grid; grid-template-columns: 1fr 2fr; } /* Subgrid falls back to auto if parent track count does not match */ .grid-child { display: grid; grid-template-columns: subgrid; } ``` Subgrid inherits parent tracks. If the parent doesn't define the expected track count, subgrid falls back to `auto` and alignment breaks silently. Define explicit tracks on the parent before using subgrid in children. ### Real-world usage - React and Next.js: Flexbox for component internals (Chakra UI buttons, navbars); Grid for app shells (Vercel dashboard) - Tailwind CSS: `flex space-x-4` for inline lists; `grid-cols-12` for page scaffolding in Shopify themes - Bootstrap 5: `.d-flex .justify-content-between` runs on Flexbox; complex multi-column forms use Grid - Material UI: Flexbox in Card and List components; Grid in data tables ### Follow-up questions **Q:** What is the difference between `justify-content` and `justify-items`? **A:** `justify-content` distributes space between tracks or items at the container level. `justify-items` aligns each item within its own grid area. Flexbox has `justify-content` but no `justify-items` - that property only applies in Grid. **Q:** How does `flex-basis` differ from `width`? **A:** `flex-basis` is the starting size before `flex-grow` and `flex-shrink` are applied. `width` is the standard box model dimension. When both are set, `flex-basis` takes priority inside a flex container. Setting `flex-basis: 0` makes all items start from zero and grow equally. **Q:** How does `grid-auto-flow: dense` work? **A:** When spanning items leave gaps in the grid, `dense` tells the browser to fill those gaps with smaller items that come later in the DOM. It improves visual density but changes visual order from DOM order, which can break keyboard navigation and screen reader flow. **Q:** Why use `gap` instead of margins on flex or grid children? **A:** `gap` only creates space between items, not on outer edges. Margins on children accumulate and can cause double spacing at container edges or after line wraps. `gap` handles this correctly in both contexts. **Q:** What is subgrid and when do you actually need it? **A:** Subgrid lets a nested grid inherit its parent's track sizes. Without it, a card inside a Grid cell defines its own internal tracks, which won't align with cards in adjacent cells. With subgrid, all cards share the same row tracks so their content lines up across columns. Available in Chrome 117+, Firefox 71+, Safari 16+. For older browsers, CSS custom properties on a shared ancestor are a practical fallback. ## Examples ### Navbar with Flexbox (React production pattern) ```jsx function Navbar() { return ( <nav style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '1rem 2rem', borderBottom: '1px solid #eee' }}> <span style={{ fontWeight: 'bold' }}>Logo</span> <ul style={{ display: 'flex', listStyle: 'none', gap: '2rem', margin: 0 }}> <li>Home</li> <li>About</li> <li>Contact</li> </ul> <button>Login</button> </nav> ); } ``` Logo on the left, navigation with consistent spacing, login button on the right. The inner `ul` is also a flex container. This is the "Grid for the shell, Flexbox for internals" pattern working in practice. ### Page layout with CSS Grid ```css .app { display: grid; grid-template-columns: 240px 1fr; grid-template-rows: 60px 1fr 40px; grid-template-areas: "header header" "sidebar content" "footer footer"; min-height: 100vh; } header { grid-area: header; } aside { grid-area: sidebar; } main { grid-area: content; } footer { grid-area: footer; } ``` Named areas make the layout readable at a glance. Change `grid-template-columns` to `1fr` inside a media query and the whole structure reflows automatically. ### Gallery with spanning items ```css .gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; } /* Featured item occupies two columns */ .gallery .featured { grid-column: span 2; } ``` Item spanning is where Grid has no Flexbox equivalent. You cannot make one flex item occupy two column widths while keeping others in a shared grid. Grid handles this natively.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.