CSS Flexbox Explained: A Visual Guide with Examples

CSS Flexbox Explained: A Visual Guide with Examples

Flexbox is the CSS tool for lining things up in a row or a column: navigation bars, button groups, card rows, form layouts, centering. Once it clicks, you'll use it every day. This guide explains every Flexbox property with a picture, so you can see what each value does instead of guessing.

Open the Flexbox playground Try every property live and copy the CSS.

Flexbox in 30 seconds

Flexbox always involves two kinds of element:

HTML
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
CSS
.container {
  display: flex;   /* that's it: the children now sit in a row */
  gap: 12px;       /* space between them */
}

Most Flexbox properties go on the container and affect all the items. A few go on an item to change just that one. This guide covers both, in that order.

The key idea: main axis and cross axis

Two flex containers: in a row the main axis runs left to right and the cross axis top to bottom; in a column they swap
The main axis follows the items. The cross axis runs across it.

Every flex container has two directions:

Why does this matter? Because justify-content always works on the main axis and align-items always works on the cross axis. When you switch to a column, the axes turn, and so do those two properties. This one fact explains most “Flexbox isn't working” moments.

Container properties

flex-direction: which way items flow

Four flex containers showing row, row-reverse, column and column-reverse
The four flex-direction values.
CSS: flex-direction
.container {
  display: flex;
  flex-direction: row;   /* row | row-reverse | column | column-reverse */
}

row is the default. column stacks items vertically, which is great for forms, sidebars and mobile layouts. The -reverse values flip the order on screen without changing the HTML.

justify-content: spread items along the main axis

Six flex containers showing justify-content flex-start, center, flex-end, space-between, space-around and space-evenly
The six justify-content values in a row.

align-items: line items up on the cross axis

Five flex containers with items of different heights showing align-items stretch, flex-start, center, flex-end and baseline
The five align-items values. The items have different heights.

Put justify-content: center and align-items: center together and you have perfect centering. More on that in how to center a div.

flex-wrap: allow a new line

Eight items in a narrow container: with nowrap they overflow on one line, with wrap they move onto a second line
nowrap keeps one line, even if it overflows. wrap starts a new line.
CSS: a wrapping row of tags
.tags {
  display: flex;
  flex-wrap: wrap;   /* nowrap (default) | wrap | wrap-reverse */
  gap: 8px;
}

By default, Flexbox squeezes everything onto one line, shrinking items, and lets them overflow if they can't shrink any further. flex-wrap: wrap lets them move to a new line instead. Use it for tags, photo galleries and any list that should flow onto more lines on small screens.

When items wrap onto several lines, align-content controls the space between those lines. It takes the same values as justify-content, and it does nothing on a single line.

gap: space between items

CSS: gap
.container {
  display: flex;
  gap: 16px;          /* same gap in both directions */
  /* gap: 24px 12px;     row gap, then column gap */
}

gap adds space between items only, never at the outer edges. It's much simpler than adding margins to items and then removing the margin from the last one.

Item properties

flex-grow: who gets the spare space?

Four rows showing flex-grow values: no growing, item 2 taking all spare space, three equal items, and item 2 growing twice as much
flex-grow decides how the leftover space is shared.

If the container is wider than the items need, there's spare space. flex-grow shares it out:

flex-shrink and flex-basis

The flex shorthand

In real code you'll usually write all three at once with flex:

CSS: common flex values
.item { flex: 1; }          /* grow 1, shrink 1, basis 0: equal widths */
.item { flex: auto; }       /* grow 1, shrink 1, basis auto: grow from content size */
.item { flex: none; }       /* grow 0, shrink 0: never change size */
.item { flex: 0 0 200px; }  /* exactly 200px, no growing or shrinking */

flex: 1 is by far the most common. It makes items share the row equally, no matter how much text is inside each one.

order and align-self

Left: item 1 with order 1 moves to the end; right: item 1 with align-self flex-end drops to the bottom while the others stay at the top
order moves one item; align-self lines up one item differently.

Three real layouts

Three layouts made with Flexbox: a navbar with the sign-up button pushed right, three equal-height pricing cards with aligned buttons, and a page with the footer at the bottom
Patterns you will build again and again.

1. A navbar

CSS: navbar
.nav {
  display: flex;
  align-items: center;   /* line everything up vertically */
  gap: 16px;
}
.nav .signup {
  margin-left: auto;     /* push this item, and anything after it, to the right */
}

In a flex container, an auto margin soaks up all the free space. That's the cleanest way to split a row into a left group and a right group.

2. Equal-height cards with aligned buttons

CSS: card row
.cards {
  display: flex;
  gap: 16px;
}
.card {
  flex: 1;                  /* equal widths */
  display: flex;
  flex-direction: column;   /* each card is a column too */
}
.card .button {
  margin-top: auto;         /* push the button to the bottom of the card */
}

Cards are the same height thanks to the default align-items: stretch. Making each card a column and giving the button margin-top: auto lines up all the buttons, however long the text is.

3. Footer at the bottom of the page

CSS: sticky footer
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
main {
  flex: 1;   /* take all the spare height, pushing the footer down */
}

On short pages, the footer no longer floats halfway up the screen.

Flexbox cheat sheet

PropertyGoes onDoes
display: flexcontainerTurns on Flexbox for the children
flex-directioncontainerRow or column
justify-contentcontainerSpacing along the main axis
align-itemscontainerAlignment on the cross axis
flex-wrapcontainerAllow items to wrap to a new line
align-contentcontainerSpacing between wrapped lines
gapcontainerSpace between items
flex (grow shrink basis)itemHow the item grows and shrinks
align-selfitemCross-axis alignment for one item
orderitemVisual order of one item

Common mistakes

Practise in the playground

The Flexbox playground: container property buttons on the left, live coloured items in the middle with item 2 stretched by flex-grow 1, item settings on the right and the generated CSS below
Click any value to see it applied, then copy the CSS.

In the Flexbox playground you can click through every container value, add and remove items, and select an item to change its flex-grow, flex-basis, align-self or order. The CSS panel only shows the properties you've changed, so you can copy exactly what you need.

Try this: set flex-direction to column and watch the note above the preview. It tells you that justify-content now works vertically.

Share your layout

Built something with Flexbox? Share a screenshot as a link with sshot.online, or share your code with the free code sharing tool. No account needed.

Frequently asked questions

What is the difference between justify-content and align-items?

justify-content positions items along the main axis, the direction they flow. align-items positions them on the cross axis. In a row, justify-content is horizontal and align-items is vertical; in a column they swap.

What does flex: 1 mean?

flex: 1 is short for flex-grow: 1, flex-shrink: 1 and flex-basis: 0. Items with flex: 1 share the available space equally, whatever their content.

Should I use Flexbox or CSS Grid?

Use Flexbox to line things up in one direction, like a navbar, a button group or a row of cards. Use Grid when you need rows and columns that line up together, like a photo grid or a full page layout. They work well together.

Why are my flex items not wrapping?

The default is flex-wrap: nowrap, which keeps all items on one line. Add flex-wrap: wrap to the container.

How do I add space between flex items?

Use the gap property on the container, for example gap: 16px. It adds space between items only, not at the edges.

Does Flexbox work in all browsers?

Yes. Flexbox, including the gap property, works in all modern browsers on desktop and mobile.

Related articles

← All guides