Why Flexbox
For years, people laid pages out with floats, tables and tricks. Flexbox (the Flexible Box Layout) was designed for exactly this job: arranging items in a line, sharing space between them, and aligning them. Navigation bars, rows of cards, a button with an icon, a centred message: Flexbox does all of these in a few lines.
Switch it on
Put display: flex on the parent. Its direct children become flex items and line up in a row:
<style>
.row { display: flex; gap: 12px; padding: 12px; background: #f1f5f9; }
.item { background: #6366f1; color: white; padding: 16px; border-radius: 8px; }
</style>
<div class="row">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three</div>
</div>Without display: flex the three blocks would stack. With it they sit side by side, each as wide as its content, and gap adds even space between them. Only direct children are affected; items nested deeper are laid out as normal.
The main axis
Flexbox thinks in two directions:
- the main axis: the direction items flow (a row by default, left to right in English);
- the cross axis: the perpendicular direction.
flex-direction changes the main axis:
.row { flex-direction: row; } /* default */
.column { flex-direction: column; } /* top to bottom */
.back { flex-direction: row-reverse; } /* reversed order */Switching to column also swaps the axes, which matters for alignment in the next lesson.
Wrapping
By default, flex items stay on one line and shrink to fit, even if that squashes them. Allow them to move onto more lines:
<style>
.row { display: flex; flex-wrap: wrap; gap: 10px; }
.card { width: 140px; padding: 16px; background: #fde68a; border-radius: 8px; }
</style>
<div class="row">
<div class="card">A</div><div class="card">B</div><div class="card">C</div>
<div class="card">D</div><div class="card">E</div><div class="card">F</div>
</div>Make the preview narrower and the cards drop onto new lines instead of shrinking. flex-flow: row wrap is a shorthand for direction and wrap.
Sharing the free space
The real power of Flexbox is how items grow and shrink. Three properties control that, usually written as the flex shorthand:
flex-basis: the starting size along the main axis (like a preferred width).flex-grow: how much of the leftover space the item takes.0means none; larger numbers claim a bigger share.flex-shrink: how readily it gives up size when there is not enough room.
<style>
.row { display: flex; gap: 8px; }
.row > div { padding: 14px; background: #bbf7d0; border-radius: 6px; }
.grow { flex: 1; } /* takes the leftover space */
.fixed { flex: 0 0 120px; } /* never grows or shrinks, 120px wide */
</style>
<div class="row">
<div class="fixed">Fixed 120px</div>
<div class="grow">Grows to fill the rest</div>
<div class="fixed">Fixed 120px</div>
</div>Common shorthands:
flex: 1: grow equally, ignore the starting size. Three items withflex: 1split the row into thirds.flex: 0 0 120px: a fixed size that neither grows nor shrinks.flex: auto: grow and shrink from the content size.flex: 2next toflex: 1: the first gets twice the free space.
A navigation bar
A typical use puts the logo on the left and links on the right by letting a spacer take the middle:
<style>
.nav { display: flex; align-items: center; gap: 16px; padding: 12px 16px; background: #0f172a; color: white; }
.logo { font-weight: bold; margin-right: auto; } /* pushes the rest to the right */
.nav a { color: #cbd5e1; text-decoration: none; }
</style>
<nav class="nav">
<span class="logo">MySite</span>
<a href="#">Home</a><a href="#">Blog</a><a href="#">Contact</a>
</nav>margin-left: auto or margin-right: auto on a flex item absorbs all the free space on that side. It is a simple and reliable trick.
Order and source order
order on an item changes the visual position without changing the HTML. Use it sparingly: keyboard and screen reader users follow the source order, so a visual order that differs can be confusing. Fix the order in the HTML where you can.
Flexbox is one-dimensional
Flexbox arranges items along one axis at a time. With wrapping, rows form, but each row is laid out independently, so columns do not line up between rows. When you need rows and columns lined up together, use Grid, covered soon.
Common mistakes
- Putting
display: flexon the items instead of the container. - Expecting grandchildren to be flex items.
- Forgetting
flex-wrapand finding items squashed on small screens. - Using margins instead of
gapand getting extra space at the edges. - Using
orderto rearrange content that screen readers will read in a different order.
Exercise
Build a row of three equal-width cards that sit in a line on wide screens and wrap to full-width stacked cards on narrow ones. Use gap for spacing.
Show one possible answer
<style>
.cards { display: flex; flex-wrap: wrap; gap: 16px; }
.card { flex: 1 1 200px; padding: 16px; background: #e0f2fe; border-radius: 8px; }
</style>
<div class="cards">
<div class="card">First</div>
<div class="card">Second</div>
<div class="card">Third</div>
</div>flex: 1 1 200px means each card starts at 200px, can grow to share space, and wraps when 200px no longer fits.
Key points
- display flex on a parent lays its direct children out in a line along the main axis.
- flex-direction sets that axis to row or column, and gap adds even spacing between items.
- flex-wrap lets items move to a new line when they run out of room.
- flex-grow, flex-shrink and flex-basis, usually written as the flex shorthand, decide how items share space.
- Flexbox lays out one dimension at a time; use Grid when you need rows and columns together.