The idea
Before flexbox, putting three things side by side, or centring something vertically, required hacks. Flexbox is a layout mode for arranging items in one direction, a row or a column, and controlling how they share space and line up. Navigation bars, toolbars, card rows, centring a dialog: flexbox handles all of them in a few lines.
Turning it on
Toko Kita's navigation is three links. By default they'd sit wherever the text flows, with no control over spacing. One line of CSS on the <nav> turns it into a flex container, and the links line up in a tidy row:
<style>
.nav { display: flex; gap: 1rem; padding: 1rem; background: #fff4e5; }
</style>
<nav class="nav">
<a href="/">Home</a>
<a href="/coffee">Coffee</a>
<a href="/equipment">Equipment</a>
</nav>
display: flex on a container makes its direct children flex items, laid out in a row. gap adds space between items (not around them), which beats margins on every item.
Two axes
Flexbox thinks in two directions:
- the main axis: the direction items flow (a row by default, left to right);
- the cross axis: perpendicular to it (vertical for a row).
justify-content aligns items along the main axis; align-items along the cross axis.
<style>
.bar { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 1rem; background: #7a4b2a; color: white; }
.bar .logo { font-size: 1.5rem; font-weight: bold; }
.bar nav { display: flex; gap: 1rem; }
.bar a { color: white; }
</style>
<header class="bar">
<span class="logo">Toko Kita</span>
<nav><a href="/coffee">Coffee</a><a href="/about">About</a><a href="/cart">Cart (2)</a></nav>
</header>
justify-content | Effect on the main axis |
|---|---|
flex-start (default) | packed at the start |
center | packed in the middle |
flex-end | packed at the end |
space-between | first and last at the edges, equal space between |
space-around / space-evenly | equal space around / between and at the edges |
align-items takes stretch (the default: items fill the cross axis), flex-start, center, flex-end and baseline.
Centring anything
For years, "how do I centre something vertically?" was one of the most asked questions in web development. With flexbox, it's a famous one-liner (well, three lines): centre along the main axis, and centre along the cross axis:
<style>
.hero { display: flex; justify-content: center; align-items: center; height: 200px; background: #fff4e5; }
</style>
<section class="hero"><p>Perfectly centred.</p></section>
Direction and wrapping
A row isn't always what you want. A row of product cards should continue on the next line when the screen is too narrow, rather than squashing every card. And a set of buttons might look better stacked on top of each other. Two properties handle that:
<style>
.cards { display: flex; flex-wrap: wrap; gap: 1rem; }
.card { width: 160px; padding: 1rem; border: 1px solid #ddd; }
.stack { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 1rem; }
</style>
<div class="cards">
<div class="card">Arabica Gayo</div><div class="card">Toraja Kalosi</div>
<div class="card">Kintamani</div><div class="card">Flores Bajawa</div>
</div>
<div class="stack"><button>Add to cart</button><button>Save for later</button></div>
flex-direction: columnmakes the main axis vertical (sojustify-contentnow works vertically).flex-wrap: wraplets items move to the next line when they don't fit, instead of squeezing.
Growing and shrinking
Items can share leftover space with the flex property on the item:
<style>
.layout { display: flex; gap: 1rem; }
.sidebar { width: 180px; flex-shrink: 0; background: #fff4e5; padding: 1rem; }
.content { flex: 1; background: #f5f5f5; padding: 1rem; }
.search { display: flex; gap: 0.5rem; margin-top: 1rem; }
.search input { flex: 1; }
</style>
<div class="layout">
<aside class="sidebar">Filters</aside>
<main class="content">Products take all the remaining width.</main>
</div>
<form class="search"><input type="search" aria-label="Search"><button>Search</button></form>
flex: 1means "grow to fill the free space" (shared equally if several items have it;flex: 2gets twice the share).flex-shrink: 0stops an item from shrinking below its width when space is tight.- The search box pattern (input grows, button keeps its size) is everywhere once you notice it.
display: flex on the container; gap for spacing; justify-content for the main axis, align-items for the cross axis; flex-direction and flex-wrap for flow; flex: 1 on an item to make it fill the remaining space.
Why this matters for clean code
Flexbox replaces piles of margins, floats and fixed widths with a few intent-revealing properties: "space these out", "centre this", "this part fills the rest". Layout code that states intent is easier to read and survives content changes: add a fourth nav link, and the layout just works.
Recap
display: flexmakes direct children flex items in a row.gapfor spacing between items.- Main axis:
justify-content(center,space-between...); cross axis:align-items(center,stretch...). flex-direction: columnfor vertical flow;flex-wrap: wrapto allow multiple lines.- On items:
flex: 1to grow,flex-shrink: 0to keep a fixed width.