← Back to Blog

CSS Grid vs Flexbox: When to Use Each Layout System (with Code Examples)

By UtilDaily Team7 min read

CSS Grid and Flexbox are both powerful layout systems, and modern web development uses them together constantly. But knowing when to reach for each one will make your layouts cleaner, more maintainable, and less reliant on hacks. Here is the definitive guide to choosing between them.

The Core Difference: 1D vs 2D

The fundamental distinction is simple:

  • Flexbox is a one-dimensional layout system. It controls layout in a single direction: either a row or a column, but not both at the same time.
  • CSS Grid is a two-dimensional layout system. It controls layout in both rows and columns simultaneously.

This does not mean Flexbox cannot handle 2D layouts (with wrapping, it can), but it handles each row or column independently. Grid treats the entire 2D space as one cohesive layout.

When to Use Flexbox

Flexbox excels at distributing space along a single axis. Use it for:

  • Navigation bars - horizontal menu items with flexible spacing
  • Button groups - a row of buttons that need equal spacing
  • Centering - vertically and horizontally centering a single element
  • Card rows - items that flow and wrap naturally
  • Form layouts - label/input pairs in a row
  • Media objects - image + text side by side

Flexbox Example: Navigation Bar

.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
}

.nav-links {
  display: flex;
  gap: 1.5rem;
  list-style: none;
}

.nav-links a {
  text-decoration: none;
  color: inherit;
}

Flexbox Example: Centering

.center-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

When to Use CSS Grid

Grid is the right choice when you need to control both rows and columns, or when the layout structure should be defined by the container rather than the content. Use it for:

  • Full page layouts - header, sidebar, main, footer arrangements
  • Magazine-style layouts - content blocks of varying sizes in a grid
  • Dashboard layouts - widgets arranged in a precise grid
  • Overlapping elements - placing items on top of each other
  • Responsive card grids - equal-sized cards that reflow based on screen width

Essential Grid Concepts

grid-template-columns and the fr Unit

The fr unit represents a fraction of the available space, similar to flex-grow in Flexbox:

.grid {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  gap: 1rem;
}
/* Creates 3 columns: 25% | 50% | 25% of available space */

You can mix fixed and flexible units:

.grid {
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 1rem;
}
/* Fixed 250px sidebar + flexible main content */

Named Grid Areas

Named grid areas are one of CSS Grid's most powerful features. They let you define layouts semantically:

.layout {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header  header"
    "sidebar main   aside"
    "footer  footer  footer";
  min-height: 100vh;
  gap: 1rem;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.aside   { grid-area: aside; }
.footer  { grid-area: footer; }

This "holy grail" layout is readable, maintainable, and easy to restructure for responsive design by redefining the grid-template-areas in a media query.

auto-fill vs auto-fit

These two keywords look similar but behave differently when there is extra space:

/* auto-fill: creates as many tracks as fit, even if empty */
.grid-fill {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
}

/* auto-fit: collapses empty tracks, stretching items to fill */
.grid-fit {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}

With 3 items in a container that could fit 5 columns: auto-fill creates 5 columns (2 empty), while auto-fit creates 3 columns that stretch to fill the container. For most card grid use cases, auto-fit is what you want.

Common Layout Patterns

Responsive Card Grid

The most common Grid pattern: cards that automatically reflow based on available space, with no media queries needed:

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
  padding: 1.5rem;
}

This creates cards that are at least 280px wide and expand to fill available space. As the viewport narrows, columns drop off naturally.

12-Column Layout

.twelve-col {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}

.span-full  { grid-column: 1 / -1; }    /* all 12 columns */
.span-half  { grid-column: span 6; }     /* 6 columns */
.span-third { grid-column: span 4; }     /* 4 columns */
.span-quarter { grid-column: span 3; }   /* 3 columns */

Responsive Holy Grail with Media Query

.page {
  display: grid;
  grid-template-areas:
    "header"
    "main"
    "sidebar"
    "footer";
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .page {
    grid-template-columns: 250px 1fr;
    grid-template-areas:
      "header  header"
      "sidebar main"
      "footer  footer";
  }
}

Can You Use Both Together?

Absolutely. Using Flexbox inside Grid cells is common and correct. Grid defines the overall page structure, and Flexbox handles alignment within individual components:

.page {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1.5rem;
}

.card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 1.5rem;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
}

.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto;
}

Here, Grid handles the card layout across the page, and Flexbox handles the internal card structure, pushing the footer to the bottom.

Quick Decision Table

ScenarioUseWhy
Navigation barFlexboxSingle row, flexible spacing
Center an elementFlexboxSimpler syntax for 1D centering
Card grid with auto-reflowGrid2D control, auto-fit handles responsiveness
Full page layoutGridNamed areas for header/sidebar/main/footer
Button groupFlexboxSingle row, gap property
Dashboard widgetsGridPrecise 2D placement, spanning
Items inside a grid cellFlexbox1D alignment within the cell
Overlapping elementsGridItems can share grid cells

Try our CSS Grid Generator to visually build grid layouts and export production-ready CSS code.

Frequently Asked Questions

Is CSS Grid replacing Flexbox?

No. Grid and Flexbox solve different problems and are designed to work together. Flexbox is still the best choice for one-dimensional layouts and component-level alignment. Grid is better for two-dimensional page layouts. Modern CSS uses both extensively, and neither is going away.

Which has better browser support?

Both CSS Grid and Flexbox have excellent browser support as of 2024. CSS Grid is supported in all modern browsers including Chrome, Firefox, Safari, and Edge. Flexbox has been supported even longer. The only concern would be very old browsers like IE 11, which has partial and buggy Grid support. For virtually all production websites today, both are safe to use.

Can I nest Grid inside Flexbox or Flexbox inside Grid?

Yes, and this is a common pattern. A typical approach is to use Grid for the overall page layout, then use Flexbox for components within grid cells (like card internals, navigation bars, or button groups). You can also nest Grid inside Flexbox, though this is less common. There is no performance penalty for nesting layout systems.

What is the CSS gap property, and does it work with both?

The gap property sets spacing between grid items or flex items. It originally only worked with Grid (as grid-gap), but now works with Flexbox in all modern browsers. It replaces the need for margin hacks and is the recommended way to add spacing between items in both layout systems.

How do I make a responsive grid without media queries?

Use grid-template-columns: repeat(auto-fit, minmax(MIN_WIDTH, 1fr)) where MIN_WIDTH is the smallest acceptable column width (e.g., 250px). This creates a grid that automatically adjusts the number of columns based on container width. No media queries needed. The auto-fit keyword collapses empty columns, and minmax() ensures items never get smaller than your minimum width.

Should I use CSS Grid for a simple two-column layout?

Either works, but Grid is often cleaner for two-column layouts where you want precise width control. grid-template-columns: 250px 1fr gives you a fixed sidebar and flexible main area in one line. Flexbox can achieve the same result but requires setting flex-basis or width on the sidebar and flex: 1 on the main area, which is slightly more verbose.

Related Tools