Skip to content
Happy Programming Guide
Start learning
Web Development

CSS Flexbox Explained

Flexbox lays items out in one direction. Once you understand the main axis, justify-content and align-items stop being guesswork — here is the model plus the four layouts you will build most.

Shelves of books in a library

Flexbox arranges items along one direction — a row or a column. Almost all the confusion around it comes from one idea, so learn that first and the properties stop being guesswork.

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

Two lines, and the children sit in a row with space between them.

The one idea: two axes#

When you write display: flex, the container gets two axes:

  • The main axis runs in the direction items flow. By default that is left to right.
  • The cross axis runs at ninety degrees to it. By default, top to bottom.

Now the two properties people mix up become obvious:

  • justify-content positions items along the main axis
  • align-items positions them across the cross axis

With the default row direction, that means horizontal and vertical respectively. Set flex-direction: column and they swapjustify-content now moves things vertically.

Container properties#

CSS
.container {
  display: flex;

  flex-direction: row;          /* row | row-reverse | column | column-reverse */
  flex-wrap: wrap;              /* nowrap (default) | wrap */
  gap: 16px;                    /* space between items */

  justify-content: flex-start;  /* along the main axis */
  align-items: stretch;         /* across the cross axis */
  align-content: flex-start;    /* spacing of wrapped LINES */
}

justify-content#

Value Result
flex-start Packed at the start (default)
flex-end Packed at the end
center Packed in the middle
space-between First and last at the edges, gaps equal
space-around Equal space around each item
space-evenly Every gap identical, including the ends

align-items#

Value Result
stretch Fill the cross axis (default) — why cards match height
flex-start Top of the row
center Middle
baseline Text baselines line up

stretch being the default is worth knowing — it is why a row of cards with different amounts of text still ends up the same height, which usually looks right and occasionally is not what you wanted.

Item properties#

CSS
.item {
  flex-grow: 0;      /* share of leftover space to take */
  flex-shrink: 1;    /* how willingly it shrinks */
  flex-basis: auto;  /* starting size before grow/shrink */

  flex: 1;           /* shorthand: grow 1, shrink 1, basis 0 */

  align-self: center;  /* override align-items for this one item */
  order: 2;            /* move it without changing the HTML */
}

flex: 1 is the one you will write most. It means “take an equal share of the available space”. Put it on two items and they split the row in half regardless of their content.

CSS
.sidebar { flex: 0 0 240px; }   /* fixed 240px, never grows or shrinks */
.content { flex: 1; }           /* takes everything else */

The four layouts you will actually build#

1. A navigation bar#

CSS
.nav {
  display: flex;
  align-items: center;
  gap: 24px;
}

.nav__logo { margin-right: auto; }   /* pushes everything else right */

margin-right: auto on one item is the neatest trick in flexbox — it absorbs all the leftover space, so you get “logo left, links right” without wrappers.

2. Perfect centring#

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

Three lines for something that used to take genuine effort.

3. A row of cards that wraps#

CSS
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  flex: 1 1 260px;   /* at least 260px, share what is left, wrap when tight */
}

No media queries needed. When there is not room for another 260px card, it moves to the next line.

CSS
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main { flex: 1; }     /* absorbs the leftover height */

The footer sits at the bottom on a short page and below the content on a long one.

The min-width: 0 trap#

This one costs people hours. A flex item’s automatic minimum size is its content, so a long unbroken string or a wide code block pushes the whole layout past the viewport:

CSS
.item {
  min-width: 0;        /* now it can shrink, and overflow can scroll */
  overflow-x: auto;
}

If your page scrolls sideways on a phone and you cannot see why, this is the first thing to try. See responsive design basics.

Flexbox or grid?#

A useful rule of thumb:

  • Flexbox when the content decides the layout — a row of buttons, a nav bar, items that should flow and wrap naturally.
  • Grid when the layout decides where content goes — a page skeleton, a gallery with aligned rows and columns.

They work together happily: a grid for the page, flexbox inside each cell. See CSS Grid explained.

Questions people ask#

Why is my flex item not shrinking?

Either flex-shrink: 0 is set, or its content has a minimum size. Add min-width: 0.

What is the difference between gap and margin?

gap applies only between items, never on the outside edges. Margins apply everywhere, so the last item gets one too and you end up removing it with :last-child.

Does flexbox work in older browsers?

Yes, universally in anything current. gap in flexbox is slightly newer than the rest but has been widely supported for years.

Should I use order to rearrange things?

Sparingly. It changes the visual order but not the DOM order, so keyboard and screen-reader users still get the original sequence. A visual order that disagrees with the reading order is an accessibility problem.

How do I make all items equal width?

flex: 1 on each gives them equal shares of the space. Add min-width: 0 if their content varies a lot.

Where to go next#

Related lessonCSS basics explained

Keep reading

Web Development

HTML Basics Explained

The HTML tags that actually matter, why semantic elements beat divs, how forms and links work, and the accessibility basics that take…

4 min read

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *