The Core Difference: 1D vs 2D
Flexbox works in one dimension at a time. You lay items out in a row or a column. Items can wrap to the next line, but each line is independent — there is no alignment between rows.
CSS Grid works in two dimensions simultaneously. You define rows and columns together, and items can be placed precisely in any cell or span multiple cells. The grid tracks (rows and columns) are aware of each other.
Think of it this way: Flexbox is like arranging books on a single shelf. Grid is like arranging furniture in a room — you are working with length and width at the same time.
If you are laying items out in a line (row or column), use Flexbox. If you need to control both rows and columns simultaneously, use Grid. Most real pages use both.
Feature Comparison Table
| Feature | Flexbox | CSS Grid |
|---|---|---|
| Dimension | One (row OR column) | Two (rows AND columns) |
| Content vs Layout | Content-driven (items size themselves) | Layout-driven (grid defines the sizing) |
| Item Placement | Sequential flow | Explicit positioning (row/column numbers) |
| Overlap | Not possible (without hacks) | Items can overlap cells |
| Gap Support | Yes (gap) |
Yes (gap, row-gap, column-gap) |
| Alignment | Main axis + cross axis | Row axis + column axis + area-level |
| Best For | Navbars, buttons, centering, single rows | Page layouts, dashboards, galleries, forms |
| Browser Support | 99%+ | 97%+ |
Flexbox Essentials
Flexbox has two actors: the flex container (the parent with display: flex) and the flex items (its direct children). The container controls direction, wrapping, and alignment. The items control their own sizing and order.
Container Properties
.container {
display: flex;
flex-direction: row; /* row | row-reverse | column | column-reverse */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
justify-content: space-between; /* flex-start | center | flex-end | space-around | space-evenly */
align-items: center; /* stretch | flex-start | center | flex-end | baseline */
gap: 16px; /* Spacing between items */
}
Item Properties
.item {
flex-grow: 1; /* How much extra space to absorb (0 = don't grow) */
flex-shrink: 1; /* How much to shrink if space is tight (0 = don't shrink) */
flex-basis: 200px; /* Starting size before grow/shrink */
/* Shorthand: flex: grow shrink basis */
flex: 1 1 200px;
/* Common shorthands */
flex: 1; /* flex: 1 1 0% — grow equally, shrink equally */
flex: none; /* flex: 0 0 auto — don't grow or shrink */
flex: auto; /* flex: 1 1 auto — grow and shrink from content size */
order: 2; /* Visual order (default is 0) */
align-self: flex-end; /* Override container's align-items for this item */
}
Generate Flexbox layouts visually with the Flexbox Playground — adjust properties with controls and copy the output CSS directly into your project.
CSS Grid Essentials
Grid also has containers and items, but with far more control over placement. The container defines the grid structure (how many columns and rows, and how big they are). Items can be placed into specific cells or left to auto-place.
Container Properties
.container {
display: grid;
/* Define columns */
grid-template-columns: 200px 1fr 200px; /* Fixed, flexible, fixed */
grid-template-columns: repeat(3, 1fr); /* Three equal columns */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* Responsive */
/* Define rows */
grid-template-rows: auto 1fr auto; /* Header, content, footer */
grid-auto-rows: minmax(100px, auto); /* Implicit row sizing */
/* Named areas */
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
gap: 20px; /* Row and column gap */
row-gap: 20px; /* Row gap only */
column-gap: 16px; /* Column gap only */
align-items: start; /* Vertical alignment within cells */
justify-items: stretch; /* Horizontal alignment within cells */
}
Item Properties
.item {
/* Place by line numbers */
grid-column: 1 / 3; /* Span from column line 1 to 3 */
grid-row: 2 / 4; /* Span from row line 2 to 4 */
/* Shorthand */
grid-column: span 2; /* Span 2 columns from current position */
/* Place by named area */
grid-area: header; /* Matches a named area from grid-template-areas */
/* Alignment within the cell */
align-self: center; /* Vertical alignment */
justify-self: end; /* Horizontal alignment */
}
Build complete grid layouts interactively with the CSS Grid Generator. Define columns, rows, and areas visually, then export production-ready CSS.
Layout: Navigation Bar (Flexbox)
A navigation bar is a row of items with varying widths. Some items push to the left, others to the right. This is a textbook Flexbox case.
<nav class="navbar">
<a href="/" class="logo">Logo</a>
<ul class="nav-menu">
<li><a href="/about">About</a></li>
<li><a href="/pricing">Pricing</a></li>
<li><a href="/docs">Docs</a></li>
</ul>
<a href="/signup" class="cta">Sign Up</a>
</nav>
.navbar {
display: flex;
align-items: center;
padding: 0 24px;
height: 64px;
background: #111;
}
.logo {
font-weight: 700;
font-size: 1.25rem;
margin-right: auto; /* Pushes everything after it to the right */
}
.nav-menu {
display: flex;
list-style: none;
gap: 24px;
margin-right: 24px;
}
.cta {
padding: 8px 20px;
background: #00d4ff;
border-radius: 8px;
color: #fff;
}
The margin-right: auto on the logo is the key trick. In Flexbox, auto margins absorb all available space in that direction, effectively pushing the nav links and CTA button to the right edge.
Layout: Card Grid (Grid)
A card grid needs equal-width columns that reflow responsively. Grid handles this in a single line of CSS — no media queries required.
<div class="card-grid">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<div class="card">Card 4</div>
<div class="card">Card 5</div>
<div class="card">Card 6</div>
</div>
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
.card {
background: #1a1a24;
border: 1px solid #2a2a3a;
border-radius: 12px;
padding: 24px;
}
The repeat(auto-fill, minmax(280px, 1fr)) pattern creates as many columns as can fit, with each card being at least 280px wide. On a 1200px screen, you get 4 columns. On a 600px screen, you get 2. On a 320px screen, you get 1. Zero media queries.
auto-fill creates empty tracks if space is left over. auto-fit collapses empty tracks, so existing items stretch to fill the row. With 2 cards in a wide container, auto-fill leaves empty grid cells while auto-fit makes the 2 cards stretch across the full width. Use auto-fill for consistent card widths; use auto-fit when you want items to stretch.
Layout: Sidebar + Content (Grid)
A sidebar layout has two columns: a fixed-width sidebar and a fluid content area. Grid makes this straightforward and maintains alignment between the sidebar and content across different row heights.
<div class="layout">
<aside class="sidebar">Sidebar</aside>
<main class="content">Main Content</main>
</div>
.layout {
display: grid;
grid-template-columns: 260px 1fr;
gap: 32px;
min-height: 100vh;
}
.sidebar {
background: #111118;
padding: 24px;
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
}
.content {
padding: 24px;
}
/* Collapse sidebar on mobile */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
}
.sidebar {
position: static;
height: auto;
}
}
The 1fr unit means "one fraction of the remaining space." After the 260px sidebar is placed, the content area gets everything else. This is more robust than percentage-based widths because the gap is handled separately.
Layout: Holy Grail (Grid + Flexbox)
The "holy grail" layout has a header, footer, sidebar, content area, and optionally a second sidebar. This is where Grid and Flexbox work best together.
<div class="page">
<header class="header">
<!-- Flexbox inside for nav items -->
</header>
<aside class="sidebar-left">Navigation</aside>
<main class="main">Content</main>
<aside class="sidebar-right">Widgets</aside>
<footer class="footer">Footer</footer>
</div>
.page {
display: grid;
grid-template-areas:
"header header header"
"left main right"
"footer footer footer";
grid-template-columns: 220px 1fr 220px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
gap: 0;
}
.header { grid-area: header; }
.sidebar-left { grid-area: left; }
.main { grid-area: main; }
.sidebar-right{ grid-area: right; }
.footer { grid-area: footer; }
/* Header uses Flexbox internally */
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 64px;
border-bottom: 1px solid #1e1e2e;
}
/* Responsive: stack on mobile */
@media (max-width: 768px) {
.page {
grid-template-areas:
"header"
"main"
"left"
"right"
"footer";
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
Named grid areas (grid-template-areas) make the layout readable at a glance. Each string represents a row, and each name represents a column in that row. Repeating a name spans the item across multiple columns. The mobile override simply stacks everything into a single column.
Responsive Patterns
Flexbox Wrapping
Flexbox items with flex-wrap: wrap and a flex-basis create a responsive layout, but without column alignment between rows.
.flex-responsive {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.flex-responsive .item {
flex: 1 1 300px; /* Grow, shrink, minimum width 300px */
}
Grid Auto-Placement
Grid gives you the same wrapping behavior but with aligned columns.
.grid-responsive {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
}
Container Queries (Modern CSS)
Container queries let you adapt based on the parent's width, not the viewport. This is powerful for reusable components.
.card-container {
container-type: inline-size;
}
.card {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
}
/* When the container is 500px+ wide, go horizontal */
@container (min-width: 500px) {
.card {
grid-template-columns: 200px 1fr;
}
}
Container queries have 91%+ browser support as of 2026 and work well with both Grid and Flexbox layouts.
Nesting Grid Inside Flexbox and Vice Versa
Grid and Flexbox can be freely nested. A common pattern: the page uses Grid for overall structure, sections inside use Flexbox for component layout, and card grids inside sections use Grid again.
/* Page: Grid */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 64px 1fr;
}
/* Header inside page: Flexbox */
.header {
grid-column: 1 / -1; /* Span full width */
display: flex;
align-items: center;
justify-content: space-between;
}
/* Main content area: contains a card grid */
.main {
padding: 24px;
}
/* Card grid inside main: Grid */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 20px;
}
/* Each card's content: Flexbox */
.card {
display: flex;
flex-direction: column;
gap: 12px;
}
.card .card-footer {
margin-top: auto; /* Push footer to the bottom */
}
The margin-top: auto trick on the last child is one of the most useful Flexbox patterns. In a column-direction flex container, it pushes the item to the bottom, creating a consistent card height regardless of content length.
Performance Considerations
Both Grid and Flexbox are highly optimized in modern browsers. In practical terms, you will not see a performance difference between them for typical layouts. Here are the edge cases to be aware of:
- Large item counts — Grid performs slightly better with hundreds of items because layout calculation is more predictable. Flexbox needs to negotiate sizing between items.
- Deep nesting — Avoid nesting more than 3-4 levels of flex/grid containers. Each level triggers a layout calculation pass.
- Auto-sizing —
grid-template-columns: auto auto autois slower thanrepeat(3, 1fr)because auto requires content measurement. Use fixed orfrunits when possible. - Animations — Animating flex or grid properties (like
flex-groworgrid-template-columns) triggers layout recalculation on every frame. Animatetransformandopacityinstead.
For the vast majority of projects, choose based on the layout you need, not performance. You can clean up your CSS output with the CSS Formatter tool.
Decision Tree: Which One to Use
Follow this decision tree when starting a new layout:
- Centering a single element? — Flexbox.
display: flex; justify-content: center; align-items: center; - A row of items (navbar, tags, buttons)? — Flexbox.
- A row of items that should stay aligned in columns when they wrap? — Grid with
auto-fill/auto-fit. - A page layout with header, sidebar, content, footer? — Grid with named areas.
- A card grid with equal-width columns? — Grid with
repeat(auto-fill, minmax(...)). - Items that need to overlap? — Grid (items can share cells).
- A component's internal layout (vertical stack of text, image, button)? — Flexbox column.
- A form layout with labels and inputs aligned? — Grid.
The best layouts use Grid for structure and Flexbox for content. They are complementary tools, not competing ones.
To experiment with colors for your layouts, the Color Converter lets you convert between HEX, RGB, HSL, and other formats instantly. And when you need to clean up your final HTML, use the HTML Beautifier.
Build CSS Layouts Visually
QTool's CSS generators let you design Grid and Flexbox layouts with a visual interface, then copy production-ready code. No syntax memorization needed.
Open Grid Generator Flexbox PlaygroundCSS Layout Tools
Frequently Asked Questions
Use CSS Grid when you need to control layout in two dimensions (rows AND columns simultaneously), such as page layouts, dashboards, and image galleries. Use Flexbox when you need to arrange items in a single direction (a row OR a column), such as navigation bars, button groups, and centering content. The simplest rule: if your layout only flows in one direction, use Flexbox. If you need to align items both horizontally and vertically at the same time, use Grid. In practice, most pages use both: Grid for the overall page structure, and Flexbox for components within each grid area.
Yes, and you should. Grid and Flexbox are complementary, not competing. A common and effective pattern is to use CSS Grid for the overall page layout (header, sidebar, main content, footer) and Flexbox for components inside each grid area (navigation links, card content, form layouts). For example, your page might use display: grid with grid-template-areas for the main structure, while the navigation bar inside the header uses display: flex to space out links. Grid items can themselves be flex containers, and flex items can be grid containers. There is no performance penalty for nesting them.
Yes, CSS Grid is supported in all modern browsers with over 97% global support as of 2026. This includes Chrome 57+, Firefox 52+, Safari 10.1+, Edge 16+, and all Chromium-based browsers. The only browsers that lack support are Internet Explorer (which only supported an older, prefixed version of the spec) and very old mobile browsers. Subgrid, a newer Grid feature, has over 90% support (Chrome 117+, Firefox 71+, Safari 16+). For the vast majority of projects, you can use CSS Grid without any fallback.
grid-template-columns defines the size of explicitly created columns in your grid. For example, grid-template-columns: 200px 1fr 200px creates exactly three columns. grid-auto-columns defines the size of columns that are created implicitly when content overflows the explicit grid. If you define 3 columns but place an item in column 5, columns 4 and 5 are auto-generated and sized according to grid-auto-columns. The same relationship exists between grid-template-rows and grid-auto-rows. In practice, you usually define your explicit grid with grid-template-columns and set grid-auto-rows to handle rows that are generated as content grows.
Use the CSS Grid repeat() function with auto-fill or auto-fit and minmax(). The pattern grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)) creates as many columns as will fit, with each column being at least 250px wide and expanding to fill available space. auto-fill creates empty tracks if there is extra space, while auto-fit collapses empty tracks so items stretch to fill the row. This single line of CSS creates a fully responsive grid that adapts from one column on mobile to multiple columns on desktop, without any media queries. Adjust the minimum value (250px in this example) to control when columns wrap.
In Flexbox, justify-content controls alignment along the main axis (the direction items flow), while align-items controls alignment along the cross axis (perpendicular to the flow). With the default flex-direction: row, justify-content aligns items horizontally (left, center, right, space-between) and align-items aligns them vertically (top, center, bottom, stretch). With flex-direction: column, the axes swap: justify-content becomes vertical and align-items becomes horizontal. A helpful way to remember: justify-content works in the direction items are laid out, and align-items works in the other direction. To center an item both ways, use display: flex; justify-content: center; align-items: center on the container.