CSS Grid vs Flexbox: When to Use Each

Grid is for two-dimensional layouts. Flexbox is for one-dimensional layouts. But real-world decisions are rarely that simple. This guide shows you exactly which tool to reach for, with side-by-side code examples for every common layout pattern.

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.

The Simple Rule

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

css — Flex Container
.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

css — Flex Items
.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

css — Grid Container
.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

css — Grid Items
.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.

html
<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>
css
.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.

html
<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>
css
.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 vs auto-fit

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.

html
<div class="layout">
  <aside class="sidebar">Sidebar</aside>
  <main class="content">Main Content</main>
</div>
css
.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.

html
<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>
css — Grid for the page, Flexbox inside components
.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.

css
.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.

css
.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.

css
.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.

css — Nested Layout
/* 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:

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:

  1. Centering a single element? — Flexbox. display: flex; justify-content: center; align-items: center;
  2. A row of items (navbar, tags, buttons)? — Flexbox.
  3. A row of items that should stay aligned in columns when they wrap? — Grid with auto-fill/auto-fit.
  4. A page layout with header, sidebar, content, footer? — Grid with named areas.
  5. A card grid with equal-width columns? — Grid with repeat(auto-fill, minmax(...)).
  6. Items that need to overlap? — Grid (items can share cells).
  7. A component's internal layout (vertical stack of text, image, button)? — Flexbox column.
  8. 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 Playground

CSS 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.

NT

Christian Bucher

We build free developer tools including CSS generators, code formatters, and color converters. 269 tool pages, all browser-based, no signup required.

269 Developer Tools, One Place

Browse 269 indexed tool pages with no QTool account required, and inspect the source on GitHub.

Open Source — Free Forever Try Free Tools

Related Tools

CSS Box Shadow Generator · Flexbox Playground - Free Tool · Emoji Picker & Search

Related Tools

HTML Beautifier & Minifier · Free JSON to YAML Converter · Free API Mock Server

Related Articles

Built by Miguel

Need a custom tool or website?

From . Delivered in 24-48h. You own the code.

View Services →