CSS Flexbox

Flexbox is a one-dimensional layout model. You arrange items in a row or a column. It solves common layout problems: centering content, distributing space between items, and making equal-height columns. It is supported in all modern browsers.

display: flex

Setting display: flex on an element makes it a flex container. All direct children become flex items and are laid out in a row by default (left to right).

.container {
  display: flex;
}

Use display: inline-flex if you want the container itself to flow inline with surrounding content.

flex-direction

flex-direction controls which direction items are laid out. The default is row.

.container {
  flex-direction: row;           /* left to right (default) */
  /* flex-direction: row-reverse;   right to left */
  /* flex-direction: column;        top to bottom */
  /* flex-direction: column-reverse; bottom to top */
}

Switching to column is what makes items stack vertically:

.stack {
  display: flex;
  flex-direction: column;
}

justify-content

justify-content aligns items along the main axis (the direction set by flex-direction).

.container {
  display: flex;
  justify-content: space-between;
}

Values:

  • flex-start: items at the start (default)
  • flex-end: items at the end
  • center: items in the middle
  • space-between: equal space between items, none at the edges
  • space-around: equal space around each item (half at edges)
  • space-evenly: equal space between items and at edges

align-items

align-items aligns items along the cross axis (perpendicular to flex-direction).

Values:

  • stretch: items stretch to fill the container height (default)
  • flex-start: items at the top
  • flex-end: items at the bottom
  • center: items vertically centred
  • baseline: items aligned by their text baseline

To centre content both horizontally and vertically:

.centred {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px;
}

gap

gap adds space between flex items. It is the modern alternative to adding margins to individual items.

.container {
  display: flex;
  gap: 16px;
}

You can also set row and column gap separately:

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 24px; /* row-gap column-gap */
}

flex-wrap

By default, flex items stay on one line even if they overflow. flex-wrap: wrap lets them move to a new line when they run out of space.

.container {
  display: flex;
  flex-wrap: wrap;       /* items wrap to new rows */
  /* flex-wrap: nowrap;     all items on one line (default) */
  /* flex-wrap: wrap-reverse; wraps in reverse order */
}

flex-grow, flex-shrink, and flex-basis

These three properties control how a flex item sizes itself relative to the available space.

  • flex-grow: how much the item grows to fill extra space. Default is 0 (no growth).
  • flex-shrink: how much the item shrinks when space is tight. Default is 1.
  • flex-basis: the starting size before growing or shrinking. Default is auto.

Use the flex shorthand to set all three at once:

.item {
  flex: 1; /* flex-grow: 1, flex-shrink: 1, flex-basis: 0 */
}

flex: 1 on all items makes them grow equally to fill available space:

.container {
  display: flex;
}

.sidebar {
  flex: 1;
}

.main {
  flex: 3; /* takes up 3x as much space as .sidebar */
}

align-self

align-self overrides align-items for a single flex item:

.special {
  align-self: flex-end;
}

order

order changes the visual position of an item without changing the HTML. Items with lower values appear first. The default is 0.

.first-visually {
  order: -1;
}

.last-visually {
  order: 1;
}

align-content

When flex-wrap: wrap is set and items span multiple rows, align-content controls the space between those rows. It has the same values as justify-content.

flex-flow

flex-flow is shorthand for flex-direction and flex-wrap together:

.container {
  flex-flow: row wrap;
}

Practical example: navbar

Logo on the left, navigation links on the right:

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
  height: 60px;
}