Flexbox

Intermediate
Layout

One-dimensional layout: a row or a column, with control over how the free space is distributed. It is the right tool for components, toolbars and anything that must adapt to its content.

Overview

Flexbox lays out children along a single axis and gives you precise control over what happens to the leftover space — or the shortfall. That makes it the natural fit for the small-scale problems that fill an interface: a header with a logo on one side and navigation on the other, a card whose button sticks to the bottom, a row of tags that wraps. The single idea to internalise is the main axis and the cross axis, because every property is defined relative to them and flex-direction swaps which is which.

The Axes

justify-content follows the main axis, align-items the cross axis — and direction swaps them.

Main axis vs cross axis
.row {
  display: flex;
  flex-direction: row;          /* main = horizontal, cross = vertical */
  justify-content: space-between;   /* along the MAIN axis */
  align-items: center;              /* along the CROSS axis */
  gap: 1rem;                        /* never margins between items */
}

/* Change the direction and both meanings swap: */
.col { flex-direction: column }   /* main = vertical, cross = horizontal */
/* now justify-content moves items UP and DOWN */

/* justify-content: flex-start | center | flex-end
                    space-between | space-around | space-evenly
   align-items:     stretch (default) | flex-start | center | flex-end
                    baseline                                        */

/* align-items: stretch is the default, which is why two cards in a
   row are automatically equal height — a genuinely useful default. */

/* Per-item override */
.logo { align-self: flex-start }

/* The classic header, in three lines */
header { display: flex; justify-content: space-between; align-items: center }

flex-grow, shrink and basis

How space is distributed. The shorthand values you will actually type.

flex: 1, and the min-width: 0 fix
/* flex: <grow> <shrink> <basis> */
.item { flex: 0 1 auto }     /* the DEFAULT: do not grow, may shrink */
.item { flex: 1 }            /* = 1 1 0  — grow to fill, ignore content
                                width, so equal siblings end up equal */
.item { flex: auto }         /* = 1 1 auto — grow, but from the
                                content's natural width */
.item { flex: none }         /* = 0 0 auto — never grow, never shrink */

/* The most common pattern: a fixed sidebar and a filling main */
.sidebar { flex: 0 0 250px }
.main    { flex: 1; min-width: 0 }

/* min-width: 0 is the fix for the single most common flex bug:
   a flex item will not shrink below its content's minimum size, so
   a long unbreakable string or a nested overflow container makes
   the whole row overflow instead of scrolling. */
.main { min-width: 0 }              /* on rows */
.col  { min-height: 0 }             /* on columns */

/* Wrapping */
.tags { display: flex; flex-wrap: wrap; gap: .5rem }
.tags > * { flex: 1 1 12rem }       /* wraps at 12rem — responsive
                                       with no media query at all */

Patterns

The layouts flexbox is genuinely best at.

auto margins, sticky footer, media object
/* Push the last item away — no floats, no absolute positioning */
.toolbar { display: flex; gap: 1rem }
.toolbar .spacer { margin-inline-start: auto }
/* auto margins absorb all the free space on that side. */

/* Card with a footer pinned to the bottom, whatever the body height */
.card { display: flex; flex-direction: column; height: 100% }
.card__body { flex: 1 }              /* takes all the slack */
.card__footer { margin-block-start: auto }   /* equivalent */

/* Sticky page footer */
body { min-height: 100dvh; display: flex; flex-direction: column }
main { flex: 1 }

/* Media object: fixed image, flexible text */
.media { display: flex; gap: 1rem; align-items: flex-start }
.media img { flex: none; width: 4rem }
.media__body { flex: 1; min-width: 0 }

/* Centring, both axes */
.center { display: flex; align-items: center; justify-content: center }

/* Choosing: flexbox when the CONTENT decides the sizes and you care
   about one axis. Grid when YOU decide the structure in two axes. */

Key Points to Remember

  • 1justify-content works along the main axis and align-items along the cross axis — flex-direction swaps which is which
  • 2align-items: stretch is the default, which is why flex siblings become equal height for free
  • 3flex: 1 means grow from a zero basis, giving equal widths; flex: auto grows from the content width
  • 4min-width: 0 on a flex item is the fix for content that refuses to shrink and overflows the row
  • 5An auto margin absorbs all free space on that side, which pushes an item to the end without floats

Interview Questions

Sign in to ask Aria
1

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

Easy
2

What does flex: 1 expand to, and how does it differ from flex: auto?

Medium
3

Why does a long string inside a flex item overflow the container, and what fixes it?

Hard

Ask Aria about Flexbox

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…