Skip to content
Topic 13 of 15
Theory

Flexbox

Why you need this

Putting elements in a row, pushing them to the edges, centring them vertically — this used to be agony with float and tables. Flexbox ("flexible boxes") solves such tasks in a couple of lines. A site header, a row of cards, buttons in a line, centring anything — that's all flex.

Container and items

Flexbox is turned on for the parent:

<style>
  .row { display: flex; }
  .row div { padding: 20px; background: gold; }
</style>
<div class="row">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>

Result: three yellow blocks in a row, although divs usually stand one under another.

  • .row is the flex container;
  • its direct children are the flex items. Grandchildren don't react to flex.

Two axes

A container has a main axis — the items go along it — and a cross axis at a right angle.

.row { flex-direction: row; }    /* main axis → left to right (the default) */
.col { flex-direction: column; } /* main axis ↓ top to bottom */

This matters: the alignment properties work relative to the axes, not "horizontally":

  • justify-content — along the main axis;
  • align-items — along the cross axis.

justify-content: along the main axis

.row { display: flex; justify-content: space-between; }
Value What it does
flex-start everything at the start (the default)
flex-end everything at the end
center in the centre
space-between the first at the start, the last at the end, the rest evenly between
space-around equal space around each item
space-evenly all gaps equal, including the edges

Result with space-between: block 1 at the left edge, block 3 at the right, block 2 in the middle.

align-items: along the cross axis

.row { display: flex; align-items: center; height: 200px; }
Value What it does
stretch stretch to the full height (the default)
flex-start / flex-end push to the start / to the end
center in the centre

Result: the blocks stand in the middle of the 200-pixel container's height.

Perfect centring — something the web lacked for a long time:

.screen {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

Result: the content is exactly in the centre of the screen, both horizontally and vertically.

gap: spacing

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

Result: 16px between the items — but not at the edges. People used to give every item a margin and then remove it from the last one; gap is simpler.

flex-wrap: wrapping

By default flex items shrink just to fit in one line. To make them wrap:

.cards { display: flex; flex-wrap: wrap; gap: 10px; }
.cards div { width: 200px; }

Result: 200px cards in a row; the ones that don't fit go to the next line. A narrow screen gets one column, a wide one gets four.

Item properties: flex-grow, flex-shrink, flex-basis

These properties are set on the children:

  • flex-basis — the "desired" size along the main axis;
  • flex-grow — what share of the free space to take (0 — don't grow);
  • flex-shrink — whether it may shrink when space is short (0 — it may not).
.sidebar { flex: 0 0 250px; } /* don't grow, don't shrink, 250px */
.main    { flex: 1; }          /* take all the free space */

Result: the sidebar is exactly 250px, and the main part stretches over all the remaining width.

The shorthand is flex: grow shrink basis. If two items have flex: 1 and flex: 2, the second gets twice as much free space.

A single item can get its own cross alignment: align-self: flex-end;. And margin-left: auto on an item "pushes" it to the right edge.

How it works inside

The browser first places the items by their flex-basis (or content width), then counts how much space is left. If there is space, it shares it by flex-grow; if there isn't enough, it takes it away by flex-shrink. Then it lays out the items along the main axis by justify-content and aligns them across by align-items.

Common mistakes

  1. display: flex on the items, not the container. Flex is turned on for the parent.
  2. Expecting it to work on grandchildren. Flex only affects direct children. A nested row is another flex container.
  3. Mixing up the axes. With flex-direction: column, justify-content works vertically, and align-items horizontally.
  4. align-items: center "doesn't work". The container is no taller than its content — there's nothing to centre in.
  5. The cards got squashed. Without flex-wrap: wrap the items shrink into one line.

Cheat sheet

Property (on whom) What it does
display: flex (parent) turn on flexbox
flex-direction: row / column the direction of the main axis
justify-content alignment along the main axis
align-items alignment along the cross axis
gap: 16px gaps between items
flex-wrap: wrap wrap onto a new line
flex: 1 (child) take the free space
flex: 0 0 200px (child) a fixed size
align-self (child) its own cross alignment

In a row with a gap

Easy+10 XP

Put the three cards inside .row in one row: make .row a flex container and set the gap between the cards to 20px.

Connect the connector to solve tasks

Task code runs on your own computer — faster and more reliable than in the browser. This needs the free CodeWithMe connector app. You only connect it once.

Looking for the connector on this computer…

  1. 1
    Download the connector for your system (Windows, macOS or Linux).Download the connectorOn the download page pick the file with your system in its name, e.g. windows-amd64.
  2. 2Run it and choose a folder for your solutions. It will install Python and Node.js there by itself when needed.
  3. 3
    Enter below the 6-digit code shown in the connector window (“Code for CodeWithMe”). If the browser asks about local network access — allow it.

The connector is open source (on GitHub), works only on your computer and runs code only after you enter the pairing code.