CSS Flexbox Tutorial: Complete Guide to Flex Properties

May 28, 20265 min read

What Is CSS Flexbox?

CSS Flexbox is a one-dimensional layout model that arranges items in rows or columns. Unlike block or inline layouts, flexbox distributes space dynamically — items grow to fill available room or shrink to avoid overflow, all without hardcoded widths.

Flexbox replaces float-based layouts, inline-block hacks, and table-based alignment. It handles distribution, alignment, and ordering in a declarative way.

Flex Container Properties

A flex container is the parent element with display: flex. These properties control how its children behave.

display

.container {
  display: flex;       /* block-level flex container */
  display: inline-flex; /* inline-level flex container */
}

Use inline-flex when the container itself should sit inline with other content — for example, a tag chip or a small icon group.

flex-direction

Sets the main axis — the direction items flow.

ValueMain Axis
rowHorizontal, left→right (default)
row-reverseHorizontal, right→left
columnVertical, top→bottom
column-reverseVertical, bottom→top
.vertical-stack {
  display: flex;
  flex-direction: column;
}

flex-wrap

Controls whether items wrap to new lines when they exceed container width.

ValueBehavior
nowrapItems shrink to fit one line (default)
wrapItems wrap onto new lines
wrap-reverseItems wrap in reverse order
.responsive-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

Without flex-wrap, items squeeze to fit. With it, items maintain their size and flow into rows — essential for responsive design.

justify-content

Distributes free space along the main axis.

ValueEffect
flex-startPack to start
flex-endPack to end
centerCenter the group
space-betweenEven gaps, no edge padding
space-aroundEqual space around each item
space-evenlyEqual space everywhere

align-items

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

ValueEffect
stretchFill container height (default)
flex-startAlign to cross-start
flex-endAlign to cross-end
centerCenter on cross axis
baselineAlign by text baseline

align-content

Controls spacing between rows when flex-wrap: wrap creates multiple lines. Has no effect with a single line.

.multi-row {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
  height: 600px;
}

gap

Sets spacing between flex items without using margins.

.container {
  display: flex;
  gap: 1rem;            /* row and column gap */
  gap: 1rem 2rem;       /* row-gap column-gap */
}

Using gap instead of margins avoids the double-spacing problem where adjacent margins collapse or stack unexpectedly.

Flex Item Properties

Flex items are direct children of a flex container. These properties control individual item behavior.

flex-grow

Defines how much an item should grow relative to siblings when extra space is available. Default is 0 (no growth).

.sidebar { flex-grow: 0; }  /* stays at its natural width */
.main    { flex-grow: 1; }  /* takes all remaining space */

If two items both have flex-grow: 1, they share extra space equally. If one has flex-grow: 2, it gets double the share.

flex-shrink

Controls how much an item shrinks when space is insufficient. Default is 1 (shrink equally).

.no-shrink {
  flex-shrink: 0; /* never shrink below its basis width */
}

Set flex-shrink: 0 on items like logos or fixed-width sidebars that should not collapse.

flex-basis

Sets the initial size of an item before growing or shrinking. Accepts any width value.

.card {
  flex-basis: 280px; /* start at 280px, then grow/shrink */
}

The flex Shorthand

flex combines flex-grow, flex-shrink, and flex-basis in one declaration.

.item {
  flex: 1;             /* flex: 1 1 0% */
  flex: 1 1 auto;      /* grow, shrink, use content size */
  flex: 0 0 200px;     /* fixed 200px, no grow, no shrink */
  flex: auto;          /* flex: 1 1 auto */
  flex: none;          /* flex: 0 0 auto — item stays at content size */
}

align-self

Overrides align-items for a single item.

.container {
  display: flex;
  align-items: flex-start;
}

.pin-bottom {
  align-self: flex-end; /* this item aligns to the bottom */
}

order

Changes the visual order of items without modifying the DOM. Default is 0.

.first-visual { order: -1; }  /* appears before siblings */
.last-visual  { order: 1; }   /* appears after siblings */

Avoid order for meaningful content sequence — screen readers follow DOM order, not visual order.

Real-World Layout Patterns

Holy Grail Layout

.layout {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.layout-body {
  display: flex;
  flex: 1;
}

.sidebar  { flex: 0 0 240px; }
.main     { flex: 1; }
.aside    { flex: 0 0 180px; }

Equal-Height Card Row

.cards {
  display: flex;
  gap: 1.5rem;
}

.card {
  flex: 1; /* all cards same width */
  display: flex;
  flex-direction: column;
}

.card-body {
  flex: 1; /* stretch to match tallest card */
}
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.content {
  flex: 1; /* pushes footer to bottom */
}

Common Pitfalls and Solutions

ProblemCauseFix
Items overflow containerMissing flex-wrapAdd flex-wrap: wrap
Item shrinks below min-widthDefault flex-shrink: 1Set flex-shrink: 0 or min-width
Unequal card heightsItems not stretchingAdd display: flex; flex-direction: column on parent
Double spacing between itemsUsing margins on both sidesReplace with gap
Content cut off in flex itemmin-width: auto allows shrinkingSet min-width: 0 or overflow: hidden
align-items not workingSingle line with no heightGive the container an explicit height

Key Takeaways

  • Flexbox is one-dimensional: items flow along one axis at a time
  • Container properties (flex-direction, justify-content, align-items) control the layout
  • Item properties (flex-grow, flex-shrink, flex-basis) control individual sizing
  • Use gap for spacing instead of margins
  • flex-wrap: wrap is essential for responsive layouts
  • Set min-width: 0 on flex items that contain text or overflow content

Try It Yourself

Experiment with every flex property using our Flexbox Generator. Toggle grow, shrink, wrap, and alignment — see the layout update live and copy the CSS.