Skip to content
RungsySign in

Flexbox & Grid

One dimension vs two — pick right and layouts stop fighting you.

40 minDifficulty 2/5css · layoutAI-writtenWritten by a model on 16 August 2026 and not yet read by a person. Checked automatically: schema, the pedagogical rules the hand-written material is held to, and every diagram parsed for real.

Before this

Why this exists

Centering something vertically used to require table-display hacks or absolute positioning with negative margins calculated by hand. Flexbox and Grid replaced that entirely — one line, `display: flex; align-items: center`, and vertical centering just works, because these layout modes were designed for exactly the problems the old model wasn't.

The mental model

Flexbox arranges items along a single line — a row or a column — and is at its best distributing space among items whose sizes can flex. Grid arranges items into a two-dimensional table of rows and columns simultaneously, and is at its best when you need to align things both horizontally and vertically at once, like a page layout.

How it works

Flexbox: one axis, and everything is relative to it

`flex-direction: row` (the default) makes the main axis horizontal; `justify-content` positions items ALONG that axis, `align-items` positions them across it, perpendicular. Switch to `flex-direction: column` and the two properties swap which physical direction they control — they're always relative to the current main axis, not fixed to a screen direction.

flex-grow, flex-shrink, and flex-basis decide how space is divided

`flex-basis` sets an item's starting size before extra space is distributed. `flex-grow: 1` on an item claims a share of any leftover space, proportional to other items' grow values. `flex-shrink` controls how much an item gives up when there isn't enough room. The shorthand `flex: 1` sets grow to 1 and shrink to 1, letting an item both expand and contract to fill available space.

Grid: define the structure once, place items into it

`grid-template-columns: 200px 1fr 1fr` defines three columns — a fixed 200px sidebar and two equal flexible columns — in one declaration on the parent. Children are placed into cells automatically, or explicitly with `grid-column` / `grid-row`, without any of them needing to know the overall structure themselves.

The `fr` unit divides remaining space proportionally

`grid-template-columns: 1fr 2fr` gives the second column exactly twice the width of the first, using whatever space remains after any fixed-size tracks are subtracted. This is the grid equivalent of flex-grow — proportional sharing of leftover space rather than an absolute size.

The mechanism

Flexbox lays items out along one axis and lets you control alignment along and across that single line. Grid defines both rows and columns as an explicit structure up front, and places items into cells within that structure — solving layouts that need alignment in two directions at once, which flexbox alone can only approximate.

flowchart LR
  subgraph Flexbox [One dimension]
    A1[item] --- A2[item] --- A3[item]
  end
  subgraph Grid [Two dimensions]
    B1[cell] --- B2[cell]
    B3[cell] --- B4[cell]
  end
Diagram source for Flexbox & Grid.

What people get wrong

Flexbox and Grid are competing options where you always pick one for your whole page.
They compose naturally: a page might use Grid for its overall two-dimensional layout (header, sidebar, main, footer) and Flexbox inside individual components (a row of buttons, a centered card) for one-dimensional arrangement. Treating them as mutually exclusive leads to forcing one tool to solve a problem the other is naturally suited for, like fighting Flexbox to align a true two-dimensional table layout.
justify-content always controls horizontal alignment.
justify-content controls alignment along the main axis, which is horizontal by default (row) but becomes vertical if flex-direction is set to column — the property doesn't change, but what it visually controls does. This trips people up specifically when they change flex-direction and the alignment properties seem to 'stop working', when actually they're now controlling the other axis.
`fr` in Grid is a percentage.
`fr` divides only the space left over after fixed-size tracks (like `200px`) are subtracted, whereas a percentage is always relative to the full container size regardless of other tracks. Confusing the two leads to layouts that don't add up as expected when mixing fixed and flexible tracks in the same grid-template-columns declaration.

When not to use it

Arranging a row of buttons, a nav bar, or centering a single item.
Flexbox — it's simpler for one-dimensional arrangement and doesn't require defining a structure you don't need.
You need precise overlap or explicit placement of items regardless of source order.
Grid's explicit `grid-column` / `grid-row` placement, which lets an item be positioned anywhere in the defined structure independent of where it appears in the HTML.

Terms

Main axis
In Flexbox, the primary direction items are laid out along, determined by flex-direction — horizontal for row, vertical for column.
fr unit
A Grid track sizing unit representing a fraction of the remaining space after fixed-size tracks are subtracted.
Grid template
The declaration on a grid container defining the number and size of its rows and/or columns.
flex-basis
An item's starting size along the main axis before flex-grow or flex-shrink adjust it to fill or fit available space.

Can you recall it?

When would you reach for Flexbox versus Grid, and why does that distinction come from how many dimensions each is designed for?

Keep track of this

Add The Browser Platform to your map and Rungsy will schedule reviews so you actually remember it.