Welcome! Flexbox is one of those CSS features that feels like a superpower the moment it clicks. It’s made for laying out items in a row or column, spacing them out, wrapping them when needed, and aligning them without doing weird “float-left-and-pray” rituals.

CSS Flexbox in one minute

CSS Flexbox is a layout mode that applies to a flex container and its flex items.

  • A flex container is an element with display: flex (or inline-flex).
  • Its direct children become flex items.
  • Flex items can grow, shrink, wrap, and align along two axes.

The big idea: you control layout using two axes:

  • Main axis: the direction items flow (row or column).
  • Cross axis: perpendicular to the main axis.
.flex {
  display: flex;
}
  
.flex {
  display: flex;
  gap: 12px;
}
  
.flex {
  display: flex;
  gap: 12px;
  justify-content: space-between;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  padding: 12px;
  background: #f2f2f2;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 700;
}
  
One
Two
Three

Your first flex container

When you set display: flex on a container, its direct children line up along the main axis.

  • display: flex makes the container a block-level element (it behaves like a block on the outside).
  • display: inline-flex makes the container an inline-level element (it behaves like text on the outside).
.flex {
  display: flex;
}
  
.flex {
  display: inline-flex;
}
  
.flex {
  display: flex;
  width: 320px;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.note {
  padding: 10px 12px;
  background: #fff7d6;
  border: 2px solid #111;
  margin-bottom: 10px;
}

.flex {
  border: 3px solid #111;
  padding: 10px;
  background: #f2f2f2;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 8px 12px;
  font-weight: 700;
}

.inline-demo {
  border: 2px dashed #111;
  padding: 8px;
}
  
This dashed box is just to show how the container behaves "on the outside".
Before
A
B
C
After

Learn more about inline-flex in the CSS Display Inline-Flex Interactive Tutorial.

Flex direction and the axes

flex-direction sets the main axis direction:

  • row (default): items go left to right (in LTR languages).
  • row-reverse: items go right to left.
  • column: items stack top to bottom.
  • column-reverse: items stack bottom to top.

When you switch direction, your alignment properties don’t change names, but they do change which axis they affect. That’s the main reason Flexbox feels confusing at first.

.flex {
  display: flex;
  flex-direction: row;
}
  
.flex {
  display: flex;
  flex-direction: column;
}
  
.flex {
  display: flex;
  flex-direction: row-reverse;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  padding: 12px;
  background: #f2f2f2;
  height: 280px;
  gap: 10px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
}
  
1
2
3
4

Wrapping: flex-wrap and flex-flow

By default, flex items try to fit on one line. If they can’t, they’ll shrink to make it work. If you want them to move onto new lines, use flex-wrap: wrap.

  • flex-wrap: nowrap (default): single line, items shrink if needed.
  • flex-wrap: wrap: items can wrap onto multiple lines.
  • flex-wrap: wrap-reverse: wraps, but flips the cross-axis stacking order.

flex-flow is shorthand for flex-direction + flex-wrap.

.flex {
  display: flex;
  flex-wrap: nowrap;
}
  
.flex {
  display: flex;
  flex-wrap: wrap;
}
  
.flex {
  display: flex;
  flex-wrap: wrap-reverse;
}
  
.flex {
  display: flex;
  flex-flow: row wrap;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
  width: 360px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
  width: 140px;
}
  
Item 1
Item 2
Item 3
Item 4
Item 5

justify-content: main-axis alignment

justify-content aligns items along the main axis. When you’re in flex-direction: row, that means horizontal alignment. In flex-direction: column, it becomes vertical alignment.

Common values:

  • flex-start (or start in newer specs)
  • center
  • flex-end (or end)
  • space-between
  • space-around
  • space-evenly
justify-content:
.flex {
  display: flex;
  justify-content: flex-start;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
}
  
Alpha
Beta
Gamma

align-items: cross-axis alignment

align-items aligns items along the cross axis. In a row, the cross axis is vertical. In a column, it’s horizontal.

  • stretch (default): items stretch to fill the cross-axis size (when possible).
  • flex-start
  • center
  • flex-end
  • baseline: aligns text baselines.
align-items:
.flex {
  display: flex;
  align-items: stretch;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
  height: 160px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
}

.item.tall {
  padding: 22px 14px;
  font-size: 22px;
}
  
Short
Taller
Short

align-content: when you have multiple lines

align-content controls how rows (or columns) are spaced along the cross axis when there are multiple lines.

Important: it only has an effect when:

  • you have wrapping (flex-wrap: wrap), and
  • there’s extra cross-axis space (usually because the container has a fixed height).
.flex {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
}
  
.flex {
  display: flex;
  flex-wrap: wrap;
  align-content: center;
}
  
.flex {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
  width: 360px;
  height: 260px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
  width: 100px;
}
  
1
2
3
4
5
6
7
8

gap: flexbox spacing without margins

gap adds space between flex items. It’s usually nicer than margins because:

  • it only creates space between items (no awkward “first/last” margin issues),
  • it works cleanly with wrapping,
  • it reads like intent: “I want space between items”.
.flex {
  display: flex;
  gap: 12px;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  flex-wrap: wrap;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
  width: 120px;
}
  
Card 1
Card 2
Card 3
Card 4
Card 5

flex-grow, flex-shrink, flex-basis up close

Let’s make the “math story” visible. We’ll keep the layout fixed-width, and change only one item’s flex values.

  • flex-basis is your starting point (often a length like 200px).
  • flex-grow decides who gets extra room.
  • flex-shrink decides who sacrifices room when there isn’t enough.
.item.focus {
  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: 130px;
}
  
.item.focus {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 130px;
}
  
.item.focus {
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: 230px;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  display: flex;
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
  width: 550px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 12px 14px;
  font-weight: 800;
  flex: 0 1 160px;
}

.item.focus {
  background: #e8f1ff;
}
  
A
Focus
C

The flex shorthand: grow, shrink, basis

The flex property is applied to flex items. It’s shorthand for:

  • flex-grow: can this item take extra space?
  • flex-shrink: can this item give up space when needed?
  • flex-basis: the item’s “starting size” before growing/shrinking.

Common patterns you’ll see:

  • flex: 0 0 auto (similar to “don’t grow, don’t shrink, size to content”)
  • flex: 1 (meaning 1 1 0% in modern flexbox behavior)
  • flex: 1 1 200px (flexible, but prefers 200px)
.item.one {
  flex: 0 1 auto;
}
  
.item.one {
  flex: 1 1 0%;
}
  
.item.one {
  flex: 1 1 220px;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  display: flex;
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
  width: 520px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 12px 14px;
  font-weight: 800;
  flex: 0 1 140px;
}

.item.one {
  background: #e8f1ff;
}
  
Item 1
Item 2
Item 3

CSS Flex order: reordering items

order changes the visual order of items without changing the HTML order.

Beginner tip: use this sparingly. Screen readers and keyboard navigation follow the DOM order, not the visual order. So if you move important content around visually, your page can become confusing to navigate.

.item.middle {
  order: 0;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  display: flex;
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 12px 14px;
  font-weight: 800;
}

.item.middle {
  background: #ffe7ef;
}
  
First
Middle
Last

align-self: per-item cross-axis control

align-items sets alignment for all items. align-self lets one item break the rules (politely).

  • Works on the cross axis.
  • Common values: auto, stretch, flex-start, center, flex-end, baseline.
.item.special {
  align-self: auto;
}
  
.item.special {
  align-self: center;
}
  
.item.special {
  align-self: flex-end;
}
  
.item.special {
  align-self: stretch;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.flex {
  display: flex;
  align-items: flex-start;
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  gap: 10px;
  height: 180px;
}

.item {
  border: 2px solid #111;
  background: #fff;
  padding: 12px 14px;
  font-weight: 800;
}

.item.special {
  background: #e8f1ff;
}
  
One
Special
Three

Common CSS flexbox layout patterns

Quick centering

To center items horizontally and vertically inside a container, the classic combo is:

  • justify-content: center
  • align-items: center
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}
  
.center {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}
  
.center {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  gap: 10px;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.center {
  border: 3px solid #111;
  background: #f2f2f2;
  height: 220px;
  padding: 12px;
}

.badge {
  border: 2px solid #111;
  background: #fff;
  padding: 10px 14px;
  font-weight: 800;
}
  
Hello
Flexbox

A simple navbar

A very common pattern is a logo on the left and links on the right. Flexbox makes it effortless: use justify-content: space-between.

Switch to the HTML view to see the structure.

.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
  
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.links {
display: flex;
gap: 10px;
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.nav {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px 14px;
}

.brand {
  font-weight: 900;
  padding: 8px 10px;
  border: 2px solid #111;
  background: #fff;
}

.links a {
  display: inline-block;
  padding: 8px 10px;
  border: 2px solid #111;
  background: #fff;
  text-decoration: none;
  color: #111;
  font-weight: 800;
}
  

Equal-height cards

Flex items in the same row can stretch to the same height automatically (that’s often align-items: stretch doing its job). Then inside each card, you can use display: flex again to push buttons to the bottom.

margin-top: auto is commonly used to push elements to the bottom of a flex container.

.grid {
  display: flex;
  gap: 12px;
}
  
.grid {
  display: flex;
  gap: 12px;
}

.card {
display: flex;
flex-direction: column;
} 
.grid {
  display: flex;
  gap: 12px;
}

.card {
  display: flex;
  flex-direction: column;
}

.card .actions {
  margin-top: auto;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  font-family: ui-sans-serif, system-ui, sans-serif;
  padding: 16px;
}

.grid {
  border: 3px solid #111;
  background: #f2f2f2;
  padding: 12px;
  align-items: stretch;
}

.card {
  border: 2px solid #111;
  background: #fff;
  padding: 12px;
  width: 180px;
  gap: 10px;
}

.card h4 {
  margin: 0;
  font-size: 18px;
}

.card p {
  margin: 0;
  font-weight: 600;
}

.btn {
  display: inline-block;
  padding: 8px 10px;
  border: 2px solid #111;
  background: #fff7d6;
  text-decoration: none;
  color: #111;
  font-weight: 800;
}
  

Starter

Short description.

Pro

A longer description that takes up more space, so the card grows taller.

Team

Medium description length.

Flexbox debugging checklist

  • Nothing happens? Make sure you set display: flex on the container (not the items).
  • Items won’t wrap? Add flex-wrap: wrap and make sure items have a width or basis that can overflow.
  • align-content does nothing? You need wrapping and extra cross-axis space.
  • Why are my items shrinking so much? Flex items default to shrinking. Consider flex-shrink: 0 on a specific item (but use it carefully).
  • Text overflows weirdly? A common fix is setting min-width: 0 on a flex item that contains long text, so it’s allowed to shrink.
  • Spacing looks off? Prefer gap over margins for consistent spacing.
  • Order changes confuse navigation? Remember: visual order and DOM order can differ. Use order carefully.

CSS Flexbox Conclusion

If you feel comfortable with containers (flex-direction, wrap, justify-content, align-items) and items (flex, align-self, order), you’re already in a great place.

When you are ready for more, check out the CSS Grid Interactive Tutorial.