So far you’ve styled elements one at a time — their color, size, spacing, and text. Now comes the part that used to be genuinely hard in CSS: layout, meaning how you arrange elements next to and around each other. Putting items in a row, spacing them out evenly, centering something perfectly — these were once awkward, finicky jobs full of hacks.
Flexbox fixed all that. It’s a layout system built for exactly this, and it makes arranging things along a row or a column refreshingly simple. If you’ve ever fought CSS to line a few things up, Flexbox is the tool that finally makes it click. Let’s dig in.
The core idea: a container and its items
Flexbox works on a container and the items inside it. You turn an element into a flex container by setting display: flex, and then its direct children automatically become flex items that you can arrange:
.container {
display: flex;
}
<div class="container">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
The moment you add display: flex to the container, its three children snap into a row, side by side, instead of stacking on top of each other. That’s the default behavior, and from there you steer everything with a handful of properties — some on the container, some on the items.
Flex properties go on the CONTAINER, not the items
The single most important thing to grasp: most flex properties go on the container (the parent), and they control how the items (the children) are arranged. So when you want to space things out or center them, you set the property on the parent — not on each child. Keep that parent-controls-the-children relationship in mind and Flexbox stops being confusing almost immediately.
Direction: rows and columns
By default, flex items lay out in a row (left to right). The flex-direction property changes that:
.container {
display: flex;
flex-direction: row; /* default — left to right */
/* flex-direction: column; — top to bottom */
}
Switch to column and the items stack vertically instead. This is the first decision to make: are you arranging things horizontally (a navbar, a row of cards) or vertically (a stacked list)? Everything after this builds on that choice.
Whichever direction you pick defines two axes: the main axis (the direction items flow) and the cross axis (the one perpendicular to it). For a row, the main axis runs horizontally and the cross axis runs vertically. That distinction matters, because the next two properties each control one of those axes.
Spacing along the main axis: justify-content
justify-content controls where items sit along the main axis — for a row, that’s left to right. This is your main tool for spacing things out:
.container {
display: flex;
justify-content: space-between;
}
The common values:
| Value | Effect |
|---|---|
flex-start |
Items packed at the start (default) |
center |
Items centered |
flex-end |
Items packed at the end |
space-between |
Equal space between items, none at the ends |
space-around |
Equal space around each item |
space-evenly |
Equal space everywhere |
space-between earns its keep — it’s exactly how you pin a logo to the left and a menu to the right in a navbar, letting the gap in the middle fill itself.
Aligning on the cross axis: align-items
align-items controls positioning along the cross axis — for a row, that’s top to bottom. This is how you line items up at the top, the bottom, or the middle:
.container {
display: flex;
align-items: center;
}
The values you’ll use are flex-start (top), center (middle), flex-end (bottom), and stretch (items stretch to fill the container’s height — this is the default). Of those, align-items: center is the one you’ll reach for over and over, because it vertically centers everything in the row in one line.
The famous “center anything” trick
Centering something perfectly — horizontally and vertically at the same time — was the stuff of legend in old CSS, the kind of problem people wrote whole blog posts about. With Flexbox, it’s two lines:
.container {
display: flex;
justify-content: center; /* center horizontally */
align-items: center; /* center vertically */
}
Whatever sits inside that container is now dead-center, both ways. This tiny pattern is one of the most-used snippets in all of CSS, and it’s well worth memorizing. Any time you need to center content inside a box, these three lines are the answer.
Gaps and wrapping
Two more container properties round out the essentials. The gap property adds clean, even space between flex items — no fiddling with margins required:
.container {
display: flex;
gap: 16px;
}
That drops a consistent 16px of space between every item — far tidier than sprinkling margins onto each child and hoping they don’t collide.
And flex-wrap lets items spill onto a new line when they don’t all fit, instead of squashing together or overflowing the container:
.container {
display: flex;
flex-wrap: wrap;
}
With wrap turned on, if a row of cards gets too wide for the screen, the leftovers drop neatly to the next line instead of breaking the layout. That’s a key ingredient for designs that adapt gracefully to different screen sizes.
Controlling individual items
Most properties live on the container, but a couple belong on the items themselves. The handiest one is flex, which controls how greedily an item grows to fill the available space:
.sidebar {
flex: 1; /* takes 1 share of the space */
}
.content {
flex: 3; /* takes 3 shares — three times as wide */
}
Here the content area ends up three times as wide as the sidebar, and together they fill the container exactly. Give every item flex: 1 instead and they split the space equally. That’s the trick behind flexible, proportional layouts.
A real example: a navbar
Let’s pull it all together into something you’d genuinely ship — a navigation bar with a logo on the left and links on the right:
.navbar {
display: flex;
justify-content: space-between; /* logo left, links right */
align-items: center; /* vertically centered */
gap: 24px;
padding: 16px;
}
<nav class="navbar">
<div class="logo">My Site</div>
<div class="links">
<a href="/">Home</a>
<a href="/about">About</a>
</div>
</nav>
That’s a clean, professional navbar in just a handful of lines — logo on the left, links on the right, everything vertically centered, with comfortable breathing room. Before Flexbox, this took floats, clearfixes, and a fair bit of swearing. Now it’s almost effortless.
Wrapping up
Flexbox is your everyday tool for one-dimensional layout — a single row or a single column — and you’ve now got its core down:
- Set
display: flexon a container, and its children become flex items. flex-directionchoosesrow(horizontal) orcolumn(vertical).justify-contentpositions items along the main axis (e.g.space-between,center).align-itemspositions them along the cross axis (e.g.center).justify-content: center+align-items: centercenters anything perfectly.gapspaces items cleanly;flex-wrap: wraplets them flow onto multiple lines.- On items,
flexcontrols how they grow and share space.
Flexbox handles laying things out in a single direction beautifully. But when you need full two-dimensional layouts — rows and columns at the same time, like a true page grid — there’s an even more powerful tool waiting. That’s up next: CSS Grid, the other half of modern layout.