BytePane

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

CSS14 min read

The Core Difference: One Dimension vs Two

The debate between CSS Flexbox and CSS Grid comes down to a simple principle: Flexbox is designed for one-dimensional layouts (a row OR a column), while Grid is designed for two-dimensional layouts (rows AND columns simultaneously). This is not a simplification -- it is the fundamental architectural difference that determines when each system excels.

Flexbox controls alignment and distribution along a single axis. Items flow in one direction, and you control how they wrap, grow, shrink, and align within that flow. Grid controls placement in both dimensions at once. You define a grid of rows and columns, then place items into specific cells or areas.

AspectFlexboxGrid
DimensionsOne (row or column)Two (rows and columns)
Content vs LayoutContent-driven (items determine flow)Layout-driven (grid determines placement)
Best forComponents, navbars, button groupsPage layouts, card grids, dashboards
Item sizingflex-grow, flex-shrink, flex-basisfr units, minmax(), auto-fill/auto-fit
Gap supportYes (gap property)Yes (gap, row-gap, column-gap)
Browser support99%+97%+

Flexbox Fundamentals

Flexbox works on a parent-child relationship. The parent (flex container) controls the flow direction and alignment. The children (flex items) control how they grow, shrink, and size themselves within that flow.

/* Container properties */
.flex-container {
  display: flex;
  flex-direction: row;          /* row | row-reverse | column | column-reverse */
  flex-wrap: wrap;              /* nowrap | wrap | wrap-reverse */
  justify-content: center;      /* flex-start | flex-end | center | space-between | space-around | space-evenly */
  align-items: center;          /* flex-start | flex-end | center | stretch | baseline */
  gap: 16px;                    /* space between items */
}

/* Item properties */
.flex-item {
  flex-grow: 1;                 /* how much extra space to absorb (0 = don't grow) */
  flex-shrink: 0;               /* how much to shrink when space is tight (0 = don't shrink) */
  flex-basis: 200px;            /* initial size before grow/shrink */
  /* Shorthand: flex: 1 0 200px; */
  align-self: flex-end;         /* override container's align-items for this item */
  order: 2;                     /* visual order (default: 0) */
}

Flexbox Example: Navigation Bar

/* Logo left, nav links center, auth buttons right */
.navbar {
  display: flex;
  align-items: center;
  padding: 0 24px;
  height: 64px;
}

.navbar .logo {
  flex-shrink: 0;              /* logo never shrinks */
}

.navbar .nav-links {
  display: flex;
  gap: 24px;
  flex: 1;                     /* takes up remaining space */
  justify-content: center;     /* centers the links */
}

.navbar .auth-buttons {
  display: flex;
  gap: 8px;
  flex-shrink: 0;              /* buttons never shrink */
}

/* HTML */
<nav class="navbar">
  <div class="logo">BytePane</div>
  <ul class="nav-links">
    <li><a href="/tools/">Tools</a></li>
    <li><a href="/blog/">Blog</a></li>
    <li><a href="/about/">About</a></li>
  </ul>
  <div class="auth-buttons">
    <button>Log in</button>
    <button>Sign up</button>
  </div>
</nav>

Flexbox Example: Centering Content

/* The classic centering trick */
.centered {
  display: flex;
  justify-content: center;    /* horizontal center */
  align-items: center;        /* vertical center */
  min-height: 100vh;          /* full viewport height */
}

/* Centering with Tailwind CSS */
<div class="flex items-center justify-center min-h-screen">
  <div>I'm perfectly centered</div>
</div>

Grid Fundamentals

CSS Grid lets you define a two-dimensional layout with explicit rows and columns. Unlike Flexbox where items flow naturally, Grid lets you place items in specific positions regardless of their source order.

/* Container properties */
.grid-container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;          /* three columns, middle is double */
  grid-template-rows: auto 1fr auto;            /* header, content, footer */
  gap: 16px;                                     /* space between cells */
  /* Or separate: row-gap: 16px; column-gap: 24px; */
}

/* Item placement */
.grid-item {
  grid-column: 1 / 3;          /* span from column line 1 to 3 */
  grid-row: 2 / 4;             /* span from row line 2 to 4 */
  /* Shorthand: grid-area: 2 / 1 / 4 / 3; */
}

/* Key units and functions */
grid-template-columns: 200px 1fr 1fr;           /* fixed + fractional */
grid-template-columns: repeat(3, 1fr);           /* three equal columns */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* responsive */
grid-template-columns: fit-content(300px) 1fr;   /* shrink-to-fit, max 300px */

Grid Example: Page Layout with Named Areas

/* Named grid areas — the most readable layout technique */
.page {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar content aside"
    "footer  footer  footer";
  grid-template-columns: 240px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  gap: 0;
}

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

/* Responsive: collapse to single column on mobile */
@media (max-width: 768px) {
  .page {
    grid-template-areas:
      "header"
      "content"
      "sidebar"
      "aside"
      "footer";
    grid-template-columns: 1fr;
  }
}

/* HTML */
<div class="page">
  <header class="header">Header</header>
  <nav class="sidebar">Sidebar</nav>
  <main class="content">Main Content</main>
  <aside class="aside">Right Sidebar</aside>
  <footer class="footer">Footer</footer>
</div>

Grid Example: Responsive Card Grid

/* Auto-responsive card grid — no media queries needed */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
}

/* auto-fill vs auto-fit:
   auto-fill: keeps empty columns (tracks) visible
   auto-fit:  collapses empty tracks, stretching items to fill space

   For card layouts, auto-fill is usually better because it
   prevents cards from stretching too wide on large screens */

/* Tailwind CSS equivalent */
<div class="grid grid-cols-[repeat(auto-fill,minmax(300px,1fr))] gap-6">
  <div class="card">Card 1</div>
  <div class="card">Card 2</div>
  <div class="card">Card 3</div>
</div>

Side-by-Side: Same Layout, Different Approaches

To really understand when to choose one over the other, let us build the same layouts with both and compare the results.

Layout 1: Media Object (Image + Text)

/* Flexbox (preferred for this pattern) */
.media-flex {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
.media-flex img {
  flex-shrink: 0;
  width: 80px;
  height: 80px;
}
.media-flex .content {
  flex: 1;          /* fills remaining space */
}

/* Grid (works, but overkill) */
.media-grid {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 16px;
  align-items: start;
}

/* Winner: Flexbox — simpler for this one-dimensional pattern */

Layout 2: Dashboard with Varied Card Sizes

/* Grid (preferred for this pattern) */
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: auto;
  gap: 16px;
}
.dashboard-grid .wide-card {
  grid-column: span 2;    /* takes 2 columns */
}
.dashboard-grid .tall-card {
  grid-row: span 2;       /* takes 2 rows */
}
.dashboard-grid .full-width {
  grid-column: 1 / -1;    /* spans all columns */
}

/* Flexbox (requires workarounds) */
.dashboard-flex {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.dashboard-flex .card {
  flex: 1 1 calc(25% - 16px);  /* approximate 4 columns */
}
.dashboard-flex .wide-card {
  flex: 1 1 calc(50% - 16px);  /* approximate 2 columns */
}
/* Problem: last row items stretch unevenly */

/* Winner: Grid — precise control over rows AND columns */

Layout 3: Form with Labels and Inputs

/* Grid (preferred — labels and inputs align perfectly) */
.form-grid {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 12px 16px;
  align-items: center;
}
.form-grid .full-width {
  grid-column: 1 / -1;
}

/* Flexbox (each row needs its own container) */
.form-flex .field {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-bottom: 12px;
}
.form-flex .field label {
  width: 150px;
  flex-shrink: 0;
}
.form-flex .field input {
  flex: 1;
}

/* Winner: Grid — labels naturally align across rows */

Decision Framework: Flexbox or Grid?

Use this quick decision guide for every layout you build. Most real-world UIs use both -- Grid for the page structure and Flexbox for components within it.

Use CaseUseWhy
Navigation barFlexboxOne-dimensional, items flow horizontally
Button groupFlexboxHorizontal row with gap spacing
Centering a single elementFlexboxjustify-content + align-items = done
Media object (icon + text)FlexboxContent-driven sizing in one direction
Card grid / galleryGridTwo-dimensional, consistent sizing
Page layout (header/sidebar/main)GridNamed areas, rows + columns
Dashboard with varied card sizesGridItems span multiple rows/columns
Form with label-input pairsGridLabels and inputs align across rows
Equal-height columnsEitherBoth handle this well
Complex page + componentsBothGrid for page, Flexbox for components

Combining Flexbox and Grid

The most effective approach is using both systems together. Grid handles the macro layout, Flexbox handles the micro layout. Here is a complete example showing how they work in harmony.

/* Page-level: Grid for the overall structure */
.app-layout {
  display: grid;
  grid-template-areas:
    "nav     nav"
    "sidebar main"
    "sidebar footer";
  grid-template-columns: 260px 1fr;
  grid-template-rows: 64px 1fr auto;
  min-height: 100vh;
}

/* Component-level: Flexbox for the navbar */
.top-nav {
  grid-area: nav;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
}

.top-nav .nav-links {
  display: flex;
  gap: 16px;
}

/* Component-level: Flexbox for sidebar links */
.side-nav {
  grid-area: sidebar;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px;
}

/* Content area: Grid for card layout */
.main-content {
  grid-area: main;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
  padding: 24px;
}

/* Inside each card: Flexbox for content flow */
.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
}

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

Responsive Design Patterns

Grid: Auto-Responsive Without Media Queries

/* The most useful responsive pattern in CSS */
.responsive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: 24px;
}

/* Why min(300px, 100%)?
   On screens narrower than 300px, 100% prevents overflow.
   This is a single line that handles every screen size. */

/* Tailwind CSS equivalent */
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
  ...
</div>

Flexbox: Wrap with Minimum Width

/* Items wrap when they can't fit at their minimum width */
.responsive-flex {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.responsive-flex > * {
  flex: 1 1 300px;     /* grow, shrink, min 300px */
  max-width: 100%;     /* prevent overflow on small screens */
}

/* Problem: last row with fewer items — they stretch to fill
   Fix: use grid instead, or add invisible spacer elements */

CSS Grid Subgrid

Subgrid is a newer Grid feature that lets child grids inherit their parent's grid tracks. This solves the long-standing problem of aligning content across sibling elements -- like making card titles, descriptions, and buttons all line up regardless of content length.

/* Parent grid defines column tracks */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

/* Each card inherits row tracks from the parent */
.card {
  display: grid;
  grid-template-rows: subgrid;   /* inherit parent's rows */
  grid-row: span 3;              /* span 3 row tracks */
}

/* Result: all card titles align, all descriptions align,
   all buttons align — even with different content lengths */

/* Without subgrid, you would need JavaScript or fixed heights */

/* Browser support (2026): Chrome 117+, Firefox 71+, Safari 16+
   That's ~92% global support */

Common Mistakes to Avoid

  1. Using Flexbox for two-dimensional card grids -- Flexbox's last row problem (leftover items stretch unevenly) is a constant headache. Use Grid with auto-fill instead.
  2. Using Grid for simple centering -- display: flex; justify-content: center; align-items: center; is simpler and more intuitive than a Grid equivalent. (Though display: grid; place-items: center; is equally valid and even shorter.)
  3. Forgetting min-width: 0 on flex items -- By default, flex items cannot shrink below their content size. If a long word or URL overflows, add min-width: 0 or overflow: hidden.
  4. Overusing order property -- Changing visual order with order in Flexbox or Grid does not change tab order or screen reader order. This creates accessibility issues. Reorder in the HTML when possible.
  5. Not using gap -- Margins on individual items create inconsistent spacing at edges. The gap property applies only between items, never at the edges.
  6. Using float or clearfix in 2026 -- If you are still using floats for layout, switch to Flexbox or Grid. Floats should only be used for their original purpose: wrapping text around images.

Flexbox and Grid in Tailwind CSS

Tailwind CSS maps every Flexbox and Grid property to utility classes. If you are using Tailwind (as this site does), here is a quick reference of the most common patterns.

<!-- Flexbox: navbar -->
<nav class="flex items-center justify-between px-6 h-16">
  <div class="text-lg font-bold">Logo</div>
  <div class="flex gap-6">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
  </div>
</nav>

<!-- Flexbox: centering -->
<div class="flex items-center justify-center min-h-screen">
  <p>Centered content</p>
</div>

<!-- Grid: responsive card layout -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
  <div class="p-4 border rounded-lg">Card 1</div>
  <div class="p-4 border rounded-lg">Card 2</div>
  <div class="p-4 border rounded-lg">Card 3</div>
</div>

<!-- Grid: page layout -->
<div class="grid grid-cols-[240px_1fr] grid-rows-[64px_1fr_auto] min-h-screen">
  <header class="col-span-2">Header</header>
  <aside>Sidebar</aside>
  <main>Content</main>
  <footer class="col-span-2">Footer</footer>
</div>

<!-- Combining both -->
<div class="grid grid-cols-3 gap-4">
  <div class="flex flex-col gap-2 p-4 border rounded-lg">
    <h3 class="font-bold">Title</h3>
    <p class="flex-1">Description</p>
    <div class="flex justify-between items-center mt-auto">
      <span>$9.99</span>
      <button>Buy</button>
    </div>
  </div>
</div>

For formatting and beautifying your CSS code, including Flexbox and Grid properties, try our CSS Formatter. It handles indentation, property ordering, and minification.

Frequently Asked Questions

Should I use Flexbox or Grid for a responsive card layout?

Use CSS Grid. The property grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)) creates a responsive grid without media queries. Cards fill available space and wrap to new rows automatically. Flexbox can do this with flex-wrap, but the last row often has inconsistent card widths because Flexbox distributes leftover space differently.

Can I use Flexbox and Grid together?

Yes, combining them is a best practice. Use Grid for the page layout (header, sidebar, main, footer) and Flexbox for components within those sections (navigation links, button groups, card content). A Grid item can be a Flex container, and vice versa. This approach uses each system for what it does best.

Is CSS Grid supported in all browsers?

Yes, CSS Grid has over 97% global browser support as of 2026. All modern browsers support it: Chrome, Firefox, Safari, Edge, and Opera. The only browser that lacked support was Internet Explorer 11, which reached end of life in June 2022. Subgrid has slightly lower support (~92%) but is well-supported in all evergreen browsers. You can use Grid in production without fallbacks.

Format Your CSS Code

Paste any CSS -- including Flexbox and Grid layouts -- into our free formatter. It handles indentation, property sorting, and minification for production-ready stylesheets.

Open CSS Formatter

Related Articles