Code of the Day
IntermediateLayout Systems

When to Use Flexbox vs Grid

Flexbox and Grid both do layout — choosing between them is a question of whether your content drives the size or your template drives the size.

Web FoundationsIntermediate6 min read
Recommended first
By the end of this lesson you will be able to:
  • State the core distinction between content-driven and template-driven layout
  • Identify which layout problems are naturally solved by Flexbox
  • Identify which layout problems are naturally solved by Grid
  • Describe how Flexbox and Grid compose at different levels of a page
  • Recognize when nested Flexbox is being misused to fake Grid behavior

You now know both Flexbox and Grid. In practice, the hardest question is not how to use them — it is when to use which. This lesson gives you a decision framework that maps to real problems, not to abstract definitions.

The core distinction

The clearest way to tell them apart:

  • Flexbox is content-driven. Items decide their own size, then the container distributes the remaining space. The layout bends to fit the content.
  • Grid is template-driven. You define the rows and columns first, then items fill them. The content fits the layout.

If you find yourself fighting the layout — pushing items around with magic margins, wondering why things do not line up across rows — you are usually on the wrong side of this distinction.

When Flexbox wins

Reach for Flexbox when:

  • You are laying out items in one direction (a row of buttons, a column of navigation links, a horizontal toolbar).
  • The number of items is dynamic — items are added or removed at runtime and you want them to wrap or grow naturally.
  • Items should size based on their content, with any remaining space distributed equally (or proportionally via flex-grow).
  • You want items to wrap onto new lines when the container is too narrow.

Real-world Flexbox territory: navigation bars, button groups, form rows, tag lists, card rows that wrap, any "put these items in a line" problem.

When Grid wins

Reach for Grid when:

  • You need rows and columns simultaneously — when alignment across both dimensions matters.
  • You are building page-level structure: header, sidebar, main content, footer. These are two-dimensional by nature.
  • Items must align across rows — if two items in different rows need their tops, bottoms, or content to line up with each other, Grid is the only layout system where that is first-class.
  • You are building a card grid where cards should form columns regardless of content height.

Real-world Grid territory: page layouts, dashboards, photo galleries, any "give me rows and columns" problem.

They compose: the most common real-world pattern

Flexbox and Grid are not competing — they operate at different levels of the component tree, and the most natural way to build a page uses both:

Page (Grid)
├── Header (Flexbox: logo + nav links)
├── Sidebar (normal flow: stacked links)
└── Main content (Grid: card grid)
    └── Each card (Flexbox: image + text + button-at-bottom)

Grid handles the macro structure (where sections live on the page). Flexbox handles the micro structure (how elements within a section are arranged). Normal flow handles simple stacks that do not need either.

The composed pattern is not a rule — it is an observation about where each system fits naturally. A header that has complex internal layout might use Grid internally. A page that is just a vertical stack of content sections might use no Grid at all. Follow the shape of the problem.

The common mistake: nested Flexbox faking Grid

A mistake that appears constantly in code reviews:

/* Trying to make three cards per row */
.card-row    { display: flex; }
.card-row .card { width: calc(33.333% - 16px); }

This works until items in different rows have different content heights — the second row's cards do not align with the first row's cards because each .card-row is an independent Flexbox container. The alignment is independent per row.

The fix is Grid:

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

Now all items share the same column tracks, and alignment across rows is automatic. The key signal: "items in different rows should align with each other" always means Grid, not nested Flexbox.

You do not need to pick one and use it exclusively. The question to ask about each container individually is: "Is this a one-dimensional arrangement (one direction, items size to content) or a two-dimensional arrangement (rows and columns, alignment across both)?" The answer tells you which to use.

A quick reference

SituationUse
Row of nav linksFlexbox
Row of buttonsFlexbox
Card grid (align across rows)Grid
Page layout (header/sidebar/main/footer)Grid
Centering a single elementFlexbox
Form fields and labels in a columnNormal flow or Flexbox
Items that wrap when narrowFlexbox
Two-column layout with equal row heightsGrid

Where to go next

Layout systems control how content flows. Sometimes you need to pull an element out of flow entirely — overlaying a modal, fixing a header to the top of the screen, adding a tooltip. Next: Positioning — the four position values and when each one applies.

Finished reading? Mark it complete to track your progress.

On this page