CSS Flexbox vs Grid: A Practical Guide to Choosing the Right Layout
This guide has a free tool → Open CSS Flexbox Generator
CSS Flexbox vs Grid: A Practical Guide to Choosing the Right Layout
CSS layout has come a long way from float-based grids and clearfix hacks. Today, developers have two powerful, purpose-built layout systems: Flexbox and CSS Grid. Both are broadly supported across all modern browsers, and both can solve many of the same problems - but they are designed with different use cases in mind.
Understanding when to reach for each one makes your CSS cleaner, more maintainable, and easier to reason about. This guide goes deep on both systems, with practical examples and clear rules for choosing between them.
---
CSS Flexbox Generator
Flexbox generator - visual CSS flexbox layout builder with live preview and ready-to-copy CSS code
CSS Grid Generator
Free online CSS grid generator - visual CSS grid layout builder with live preview and code export
CSS Animation Generator
Free online CSS animation generator - generate CSS keyframe animations visually
The One-Sentence Difference
Flexbox is for laying out items in a single direction - either a row or a column. CSS Grid is for laying out items in two dimensions simultaneously - rows and columns at the same time.
That distinction drives everything else. If you internalize it, most "which should I use?" questions answer themselves.
---
Flexbox: One-Dimensional Layout
Flexbox is built around the concept of a single axis. You declare a flex container, choose whether items flow in a row or column, and then control how they distribute along that axis and align on the perpendicular axis.
How Flexbox Thinks About Space
Flexbox has two axes:
- The main axis: the direction items flow (horizontal for rows, vertical for columns)
- The cross axis: perpendicular to the main axis
justify-content controls spacing along the main axis. align-items controls alignment on the cross axis. Once you understand this, every flex property makes intuitive sense.
.container {
display: flex;
flex-direction: row; /* Items flow left to right */
justify-content: center; /* Center items on the horizontal axis */
align-items: center; /* Center items on the vertical axis */
}Navigation Bar
Navigation is the classic flexbox use case. It is a list of items flowing in one direction, with some alignment logic:
.nav {
display: flex;
align-items: center;
gap: 16px;
padding: 0 24px;
height: 64px;
background: #fff;
border-bottom: 1px solid #e5e7eb;
}
.nav .logo {
font-weight: 700;
font-size: 1.25rem;
}
.nav .links {
display: flex;
gap: 8px;
}
.nav .actions {
margin-left: auto; /* Pushes this element to the far right */
display: flex;
gap: 8px;
align-items: center;
}<nav class="nav">
<div class="logo">MyApp</div>
<div class="links">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/blog">Blog</a>
</div>
<div class="actions">
<a href="/login">Log in</a>
<a href="/signup">Sign up</a>
</div>
</nav>The margin-left: auto on .actions is a powerful flexbox technique. Auto margins consume all remaining free space on the axis, effectively pushing the element to the opposite end of the container. This is cleaner than using justify-content: space-between when only one element needs to be pushed.
Wrapping Card Row
Flexbox handles content that should wrap to a new line as space runs out:
.card-row {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 280px;
/* flex-grow: 1 - cards can grow to fill available space */
/* flex-shrink: 1 - cards can shrink if needed */
/* flex-basis: 280px - minimum preferred width before growing */
min-width: 0; /* Prevents overflow from long text */
}This creates a row of cards that wraps to a new line when they cannot fit, and each card grows to fill available space. You get a responsive layout without media queries.
Vertical Centering
Before flexbox, vertically centering an element was one of the most frustrating CSS challenges. Now:
.centered-container {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}Two lines. That is all it takes to center anything both horizontally and vertically within a container.
Form Layout
Inline form elements with a label and input side by side:
.form-field {
display: flex;
align-items: baseline;
gap: 12px;
margin-bottom: 16px;
}
.form-field label {
flex: 0 0 120px; /* Fixed width label, does not grow or shrink */
text-align: right;
font-weight: 500;
}
.form-field input {
flex: 1; /* Input takes remaining space */
padding: 8px 12px;
border: 1px solid #d1d5db;
border-radius: 6px;
}<div class="form-field">
<label for="name">Full Name</label>
<input type="text" id="name" name="name">
</div>align-items: baseline ensures the label and input text align by their text baseline even if the input has padding. This is more precise than align-items: center for text-adjacent elements.
Key Flexbox Properties Reference
#### Container Properties
.flex-container {
display: flex;
/* Direction of flow */
flex-direction: row; /* row | row-reverse | column | column-reverse */
/* Wrapping */
flex-wrap: nowrap; /* nowrap | wrap | wrap-reverse */
/* Shorthand for flex-direction + flex-wrap */
flex-flow: row wrap;
/* Main axis alignment */
justify-content: flex-start; /* flex-start | flex-end | center | space-between | space-around | space-evenly */
/* Cross axis alignment (single line) */
align-items: stretch; /* stretch | flex-start | flex-end | center | baseline */
/* Cross axis alignment (multiple lines when wrapped) */
align-content: normal; /* normal | flex-start | flex-end | center | space-between | space-around | stretch */
/* Gap between items */
gap: 16px; /* row-gap and column-gap in one */
row-gap: 16px;
column-gap: 12px;
}#### Item Properties
.flex-item {
/* Shorthand for flex-grow, flex-shrink, flex-basis */
flex: 0 1 auto; /* default */
flex: 1; /* grow: 1, shrink: 1, basis: 0% */
flex: 1 0 200px; /* grow: 1, shrink: 0, basis: 200px */
flex: none; /* flex: 0 0 auto - item does not flex */
/* Control growth */
flex-grow: 1; /* Proportion of free space this item takes */
flex-shrink: 0; /* Prevent item from shrinking */
flex-basis: 200px; /* Initial size before flexing */
/* Override container alignment for this item */
align-self: center; /* auto | flex-start | flex-end | center | baseline | stretch */
/* Override visual order */
order: -1; /* Negative values appear first */
/* Auto margins */
margin-left: auto; /* Pushes item to the right */
margin-right: auto; /* Centers item if both sides are auto */
}When Flexbox Is the Right Choice
- Navigation bars and toolbars
- Horizontal or vertical lists of items
- Centering content within a container
- Distributing space between items of varying or unknown sizes
- Card rows that should wrap responsively
- Inline form fields with labels
- Button groups and tag lists
- Any single-direction layout where content drives the size
---
CSS Grid: Two-Dimensional Layout
CSS Grid thinks in terms of a defined structure. You declare the grid - how many columns, how many rows, what sizes - and then place items into that structure. The grid is defined independently of its content.
How Grid Thinks About Space
Grid has two axes just like Flexbox - rows and columns - but operates on both simultaneously. Items are placed into cells, which are intersections of row tracks and column tracks.
The key mental shift: with Flexbox, content sizes determine layout. With Grid, layout structure is declared first and content fills it.
Page Layout with Grid
The dashboard layout is where Grid shines. A full page with a header, sidebar, main area, aside, and footer:
.page {
display: grid;
grid-template-columns: 240px 1fr 300px;
grid-template-rows: 64px 1fr 48px;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
min-height: 100vh;
gap: 0;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }<div class="page">
<header class="header">Header</header>
<nav class="sidebar">Sidebar</nav>
<main class="main">Main content</main>
<aside class="aside">Right panel</aside>
<footer class="footer">Footer</footer>
</div>grid-template-areas lets you describe the layout visually using named zones. The string representation maps directly to the visual grid. This is one of the most readable CSS layout patterns available.
Responsive Card Grid
Grid makes equal-width card grids trivial:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}This single declaration creates a fully responsive grid:
repeat(auto-fill, ...)creates as many columns as can fitminmax(280px, 1fr)says each column is at least 280px wide and can grow to fill available space- Cards automatically reflow as the viewport changes - no media queries needed
Explicit Item Placement
Grid allows items to span multiple cells and be placed at specific positions:
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 200px);
gap: 16px;
}
/* A featured item that spans 2 columns and 2 rows */
.featured {
grid-column: 1 / 3; /* Columns 1 through 3 (spans 2) */
grid-row: 1 / 3; /* Rows 1 through 3 (spans 2) */
}
/* Shorthand */
.wide-item {
grid-column: span 2; /* Span 2 columns from current position */
}
.tall-item {
grid-row: span 3; /* Span 3 rows from current position */
}
/* Negative indices count from the end */
.full-width {
grid-column: 1 / -1; /* Span all columns */
}Overlapping Elements
Grid allows items to occupy the same cell, enabling overlapping layouts that would require absolute positioning in other approaches:
.hero {
display: grid;
grid-template-areas: "content";
}
.hero-image {
grid-area: content;
width: 100%;
height: 400px;
object-fit: cover;
}
.hero-text {
grid-area: content; /* Same area - overlaps the image */
display: flex;
flex-direction: column;
justify-content: center;
padding: 48px;
z-index: 1;
color: white;
}Both .hero-image and .hero-text are assigned to the same grid area, causing them to overlap. Combined with z-index, this creates a layered effect without taking any element out of the document flow.
Key Grid Properties Reference
#### Container Properties
.grid-container {
display: grid;
/* Define columns */
grid-template-columns: 200px 1fr 1fr;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* Define rows */
grid-template-rows: 64px 1fr auto;
/* Named areas */
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
/* Implicit rows for auto-placed items */
grid-auto-rows: 200px;
grid-auto-columns: 1fr;
grid-auto-flow: row; /* row | column | dense */
/* Gaps */
gap: 16px;
row-gap: 16px;
column-gap: 24px;
/* Alignment of all items in their cells */
justify-items: stretch; /* stretch | start | end | center */
align-items: stretch;
/* Alignment of the grid tracks in the container */
justify-content: start; /* start | end | center | space-between | space-around | space-evenly */
align-content: start;
}#### Item Properties
.grid-item {
/* Column placement */
grid-column-start: 1;
grid-column-end: 3;
grid-column: 1 / 3; /* Shorthand */
grid-column: 1 / span 2; /* Start at 1, span 2 columns */
grid-column: span 2; /* Auto-placed, span 2 */
/* Row placement */
grid-row: 2 / 4;
grid-row: span 2;
/* Named area */
grid-area: header;
/* Override container alignment for this item */
justify-self: center;
align-self: end;
}When Grid Is the Right Choice
- Page-level layouts (header, sidebar, main, footer)
- Responsive image galleries and card grids
- Dashboard layouts with multiple regions
- Data tables and form layouts requiring column alignment across rows
- Magazine-style editorial layouts
- Any two-dimensional structure where items should align in both rows and columns
- Layouts requiring items to span multiple rows or columns
- Overlapping element compositions
---
Side-by-Side Comparison
| Feature | Flexbox | CSS Grid |
|---|---|---|
| Dimensions | One axis at a time | Both axes simultaneously |
| Layout model | Content-driven (items determine layout) | Structure-driven (layout defines placement) |
| Alignment | Along main and cross axes | Within and across both row and column tracks |
| Wrapping | Items wrap to new lines | Explicit rows and columns |
| Spanning | Items can grow/shrink, not span | Items can span multiple rows and columns |
| Overlap | Not natively supported | Native via same grid-area assignment |
| Unknown item count | Handles naturally | Auto-fill/auto-fit adapts |
| Named zones | Not available | grid-template-areas provides visual naming |
| Browser support | Universal | Universal (IE11 with prefixes, avoid) |
| Best primary use | Components and UI widgets | Page sections and data grids |
---
Combining Flexbox and Grid
The most maintainable layouts use both systems for what each does best. Grid defines the macro structure; Flexbox handles the micro layout within each region.
/* Grid for the macro page structure */
.app {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr;
grid-template-areas:
"sidebar header"
"sidebar content";
height: 100vh;
}
/* Flexbox for the header region */
.header {
grid-area: header;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
border-bottom: 1px solid #e5e7eb;
}
/* Grid for the card list in content */
.content {
grid-area: content;
padding: 24px;
overflow-y: auto;
}
.card-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 16px;
}
/* Flexbox for layout within each card */
.card {
display: flex;
flex-direction: column;
border: 1px solid #e5e7eb;
border-radius: 8px;
overflow: hidden;
}
.card .card-body {
flex: 1; /* Takes remaining vertical space in the card */
padding: 16px;
}
.card .card-footer {
/* Stays at the bottom regardless of card body height */
padding: 12px 16px;
border-top: 1px solid #e5e7eb;
display: flex;
justify-content: flex-end;
gap: 8px;
}This pattern - Grid for sections, Flexbox for components - is the standard approach in production applications. They are complementary tools, not competing ones.
---
Common Mistakes
Reaching for Grid When Flexbox Is Simpler
Not everything needs a two-dimensional layout. If you are arranging items in a single row or column, Flexbox is simpler and more appropriate:
/* Overkill for a simple horizontal button group */
.button-group {
display: grid;
grid-template-columns: auto auto auto;
gap: 8px;
}
/* Better - this is a single-direction layout */
.button-group {
display: flex;
gap: 8px;
}Grid requires you to know the number of columns in advance (or use auto-fill). Flexbox naturally handles variable numbers of items.
Nesting Flexbox to Fake a Grid
If you find yourself nesting multiple levels of Flexbox containers to get items to align across "rows", you probably want Grid:
/* Flexbox hell - three levels of nesting to approximate a grid */
.outer { display: flex; flex-direction: column; gap: 16px; }
.row { display: flex; gap: 16px; }
.item { flex: 1; }
/* Better - just use Grid */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}A grid layout that requires alignment in both directions should use Grid, not nested Flexbox.
Not Using gap
Both Flexbox and Grid support the gap property. Using margins on child elements for spacing creates margin collapse issues, harder-to-maintain code, and unexpected behavior at container edges.
/* Old way - margins on children */
.item { margin-right: 16px; margin-bottom: 16px; }
.item:last-child { margin-right: 0; }
/* Modern way - gap on the container */
.container {
display: flex; /* or grid */
gap: 16px;
}gap only creates space between items, not on the outer edges of the container. This is almost always what you want.
Forgetting grid-auto-rows for Implicit Rows
When items overflow the explicitly defined rows in a Grid layout, they go into implicit rows. Without grid-auto-rows, these implicit rows have auto height and may not match your expected layout:
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 200px 200px; /* Only 2 rows defined */
/* Items in rows 3+ will have auto height */
}
/* Fix: set implicit row height */
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px; /* All auto-created rows will be 200px */
gap: 16px;
}Using justify-content When you Mean align-items
In Flexbox, which property controls which axis depends on flex-direction. This trips up many developers:
/* flex-direction: row (default) */
.row { display: flex; }
/* justify-content -> horizontal axis */
/* align-items -> vertical axis */
/* flex-direction: column */
.col { display: flex; flex-direction: column; }
/* justify-content -> vertical axis */
/* align-items -> horizontal axis */When you switch flex-direction, the axes flip. Keep this in mind when centering in a column layout.
---
Responsive Layout Patterns
The Holy Grail Layout
The classic three-column layout with header and footer, fully responsive:
.holy-grail {
display: grid;
grid-template-areas:
"header"
"main"
"sidebar"
"aside"
"footer";
grid-template-rows: auto 1fr auto auto auto;
min-height: 100vh;
}
@media (min-width: 768px) {
.holy-grail {
grid-template-columns: 200px 1fr 200px;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
grid-template-rows: auto 1fr auto;
}
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }On mobile, all sections stack vertically. On wider screens, the three-column layout activates. The named grid areas make the responsive transformation easy to read.
Masonry-Like Layout
While true masonry requires JavaScript, CSS Grid can create a close approximation:
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: 10px;
gap: 16px 16px;
}
/* Each item spans a number of rows proportional to its content height */
/* (row span must be set via JavaScript based on measured height) */True CSS Masonry layout is in the CSS Grid specification as grid-template-rows: masonry but browser support is still experimental (2026). Use the JavaScript approach for production.
---
Using ToolBox to Build Layouts Visually
Building CSS layouts by editing properties and refreshing the browser is slow. ToolBox has interactive visual generators for both layout systems:
CSS Flexbox Generator
The CSS Flexbox Generator lets you:
- Visually toggle flex direction, wrap, justify-content, and align-items
- See the layout update in real time as you adjust properties
- Add items and control individual item properties like flex-grow and order
- Copy the exact CSS for your configuration
This is the fastest way to experiment with flex properties and understand how they interact, especially justify-content vs align-items and how they behave differently in row vs column direction.
CSS Grid Generator
The CSS Grid Generator lets you:
- Define column and row counts visually
- Set column widths using fr units, px, %, or minmax
- Place items and define spans interactively
- Copy the generated CSS for use in your project
Start with the grid generator when designing a new page layout, and use the generated CSS as the starting point for your stylesheet.
---
Additional CSS Tools
- CSS Animation Generator - Create keyframe animations visually
- Box Shadow Generator - Build box shadows with a visual editor
- Border Radius Generator - Create complex border-radius shapes
- Gradient Generator - Build linear and radial gradients visually
- Tailwind to CSS Converter - Convert Tailwind utility classes to equivalent plain CSS
- Color Contrast Checker - Verify that your layout colors meet WCAG accessibility standards
- CSS Units Converter - Convert between px, rem, em, vw, and other CSS units
---
Quick Decision Guide
Use this as a mental checklist:
| Question | Answer: Flexbox | Answer: Grid |
|---|---|---|
| How many directions are items laid out? | One | Two |
| Do items need to align across multiple rows? | No | Yes |
| Is the number of items known in advance? | No | Either |
| Should items span multiple rows or columns? | No | Yes |
| Is this a component or a page section? | Component | Page section |
| Do items need to overlap? | No | Yes |
| Is item sizing content-driven? | Yes | Either |
---
Try It Now
Build and experiment with CSS layouts visually:
- CSS Flexbox Generator - Visualize and generate Flexbox layouts
- CSS Grid Generator - Visualize and generate Grid layouts
Free, private, and no signup required. The generated CSS is yours to copy and use immediately.
Related Tools
Free, private, no signup required
CSS Formatter
Free online CSS formatter - format and beautify CSS code with configurable options
HTML to JSX Converter
Free online HTML to JSX converter - convert HTML markup to valid React JSX with automatic attribute and style transformations
Meta Tag Generator
Free online meta tag generator - generate SEO meta tags, Open Graph, and Twitter Card markup for your website
You might also like
Want higher limits, batch processing, and AI tools?