⌨️ Web development

CSS Grid or Flexbox: when to use each one

Practical differences between CSS Grid and Flexbox: one- and two-dimensional layouts, code examples and simple criteria for picking the right tool.

Flexbox and CSS Grid are the two modern CSS layout systems, and every current browser supports them. They are not competitors: they solve different problems, and they almost always coexist on the same page. Understanding the basic difference stops you from forcing one of them to do a job it was not designed for.

The essential difference: one dimension or two

Flexbox arranges items along a single axis at a time, horizontal or vertical. Items can wrap, but each line is calculated independently of the others: there is no alignment between columns of different lines.

Grid works in two dimensions at once. You define rows and columns and then place items into cells. Items in the second row line up exactly with the columns of the first.

Another useful way to look at it: Flexbox starts from the content (items are distributed according to their size), Grid starts from the container (you draw the grid first, then put things in it).

When Flexbox is the natural choice

Flexbox excels at linear components:

  • navigation bars with the logo on the left and links on the right;
  • groups of buttons or tags that wrap;
  • vertical and horizontal centring of an element;
  • a row with a text field that expands and a fixed-width button.
.toolbar {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.toolbar .search {
  flex: 1;        /* takes the available space */
}
.toolbar .logo {
  margin-right: auto; /* pushes the rest to the right */
}

The flex property (shorthand for flex-grow, flex-shrink and flex-basis) is the heart of Flexbox: it decides how each item grows or shrinks when the space changes.

When Grid is the natural choice

Grid is the right tool when you care about alignment across rows and columns:

  • the overall page layout (header, sidebar, content, footer);
  • card galleries whose columns must line up;
  • forms with labels and fields in columns;
  • editorial compositions with items spanning several cells.

A responsive gallery without media queries:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1.5rem;
}

The browser creates as many columns as fit, each at least 220 pixels wide, and shares out the remaining space. With Flexbox you would get a similar result, but the incomplete last row would stretch differently from the others.

Named areas

One of Grid's most readable features is grid-template-areas, which lets you "draw" the layout:

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}
.page > header { grid-area: header; }
.page > aside  { grid-area: sidebar; }
.page > main   { grid-area: main; }
.page > footer { grid-area: footer; }

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

Changing the layout on small screens becomes a matter of rewriting a few lines.

Combining them is the norm

In everyday practice you use Grid for the structure and Flexbox inside individual components. The page is a grid; the card inside the grid uses a column Flexbox to keep the button always at the bottom:

.card {
  display: flex;
  flex-direction: column;
}
.card .actions {
  margin-top: auto;
}

This way all the cards in a row have their button aligned at the bottom, even when the texts differ in length.

Subgrid

When you want the inner parts of different cards to line up with each other (titles, texts and buttons at the same height), Grid offers subgrid: the child element inherits the tracks of its parent's grid. Modern browsers support it, and it removes many fixed-height hacks.

Shared properties

Some concepts apply to both and make it easier to switch from one to the other:

Property Flexbox Grid
gap space between items space between rows and columns
justify-content distribution on the main axis distribution of tracks
align-items alignment on the cross axis vertical alignment in the cell
order changes visual order changes visual order

Be careful with order and with Grid's free placement: they change the visual order but not the DOM order. People navigating with a keyboard or a screen reader follow the source order, so overly aggressive visual reordering causes confusion.

A practical rule for deciding

When you are unsure, ask yourself three questions:

  1. Do I need both horizontal and vertical alignment between different items? Then Grid.
  2. Do items need to adapt to their own size along a row or a column? Then Flexbox.
  3. Am I defining the structure of a page or a large section? Usually Grid; for inner components, often Flexbox.

In my web development work I notice that many "impossible" layout problems come from picking the wrong tool: a gallery built with Flexbox that will not align, or a navigation bar built with Grid that breaks when a link gets longer.

In short

  • Flexbox arranges items along one axis; Grid works on rows and columns together.
  • Flexbox is ideal for bars, button groups and linear components.
  • Grid is ideal for page layouts, galleries and column-based forms.
  • grid-template-areas and repeat(auto-fill, minmax()) make responsive design very simple.
  • Use them together and do not stray too far from the DOM order visually.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also