CSS Flexbox Basics
A practical teen tutorial on CSS Flexbox: turn a container into a flex container, control direction, justify-content, align-items, gap and flex-grow to build clean, modern layouts, with runnable code and a quiz.
Key takeaways
- display: flex turns an element into a flex container and its children into flex items
- flex-direction sets the main axis: row (default) or column
- justify-content spaces items along the main axis
- align-items positions items along the cross axis
- gap adds even spacing between items, and flex: 1 lets items grow to fill space
What problem does Flexbox solve?
Before Flexbox, lining things up in CSS was painful. Centering a box vertically, spacing buttons evenly, or making columns equal height took hacks with floats and margins. Flexbox (the Flexible Box Layout) fixes all of that. It's a layout system designed to arrange items in a single direction β a row or a column β and distribute space between them intelligently.
The core idea is simple: you mark one element as a flex container, and its direct children automatically become flex items you can align and space with a handful of properties. In this lesson you'll learn the essential ones and build a working navbar and card row. This builds on Styling Web Pages with CSS, so make sure you're comfortable with basic selectors first.
Step 1: Turn on flex
You start by setting display: flex on the container β the element that holds the items you want to arrange:
.container {
display: flex;
}
With HTML like this:
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>
The moment you add display: flex, the three boxes line up in a row side by side, instead of stacking on separate lines like normal <div>s do. That's the default behaviour. Everything else is about controlling how they line up.
The two axes
Flexbox thinks in terms of two directions:
- The main axis β the direction items flow along (horizontal by default).
- The cross axis β the direction at 90Β° to it (vertical by default).
This matters because two key properties work on different axes: justify-content works along the main axis, and align-items works along the cross axis. Keep this picture in mind and Flexbox stops feeling random.
Step 2: flex-direction
flex-direction sets which way the main axis points:
.container {
display: flex;
flex-direction: row; /* default: left to right */
}
The four values:
| Value | Items flow |
|---|---|
row | left β right (default) |
row-reverse | right β left |
column | top β bottom |
column-reverse | bottom β top |
Switching to column instantly stacks the items vertically. Notice that when you change the direction, the main and cross axes swap too β so justify-content now works vertically and align-items horizontally.
Step 3: justify-content (main axis)
justify-content controls how items are spaced along the main axis:
.container {
display: flex;
justify-content: space-between;
}
The most useful values:
flex-startβ bunched at the start (default).centerβ centered as a group.space-betweenβ first and last hug the edges, equal gaps between.space-aroundβ equal space around each item.space-evenlyβ perfectly equal gaps everywhere.
space-between is what you'll reach for in a navbar: logo on the left, links on the right.
Step 4: align-items (cross axis)
align-items controls how items line up on the cross axis. In a default row, that's vertical alignment:
.container {
display: flex;
align-items: center; /* vertically center the items */
height: 200px;
}
Common values:
stretchβ items stretch to fill the container's height (default).centerβ items centered on the cross axis.flex-start/flex-endβ pinned to the top / bottom.
The famous "how do I center a box both ways?" question is now trivial:
.container {
display: flex;
justify-content: center; /* center horizontally */
align-items: center; /* center vertically */
height: 300px;
}
That's it. One container, two lines, perfectly centered.
Step 5: gap and flex-grow
To put even spacing between items without fiddly margins, use gap:
.container {
display: flex;
gap: 16px; /* 16px between every item */
}
And to let items grow to fill leftover space, give them flex:
.item {
flex: 1; /* every item takes an equal share of the free space */
}
If you give one item flex: 2 and the others flex: 1, that one takes twice the share. This is how you make flexible, proportional columns.
A complete worked example
Here's a small page with a navbar and a row of three equal cards, all built with Flexbox. Save it as an .html file and open it in a browser. Resize the window to watch the cards share the space.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Flexbox Demo</title>
<style>
body { font-family: sans-serif; margin: 0; }
/* Navbar: logo left, links right, vertically centered */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background: #1e293b;
color: white;
padding: 16px 24px;
}
.links {
display: flex;
gap: 20px;
}
/* Card row: three equal, growing cards */
.cards {
display: flex;
gap: 16px;
padding: 24px;
}
.card {
flex: 1; /* equal share of the space */
background: #e0f2fe;
border-radius: 10px;
padding: 20px;
text-align: center;
}
</style>
</head>
<body>
<nav class="navbar">
<strong>MySite</strong>
<div class="links">
<span>Home</span>
<span>About</span>
<span>Contact</span>
</div>
</nav>
<div class="cards">
<div class="card"><h2>Fast</h2><p>Loads instantly.</p></div>
<div class="card"><h2>Simple</h2><p>Easy to use.</p></div>
<div class="card"><h2>Modern</h2><p>Built with Flexbox.</p></div>
</div>
</body>
</html>
Reading the result:
- The navbar uses
justify-content: space-betweento push the logo and links apart, andalign-items: centerto line them up vertically. - The cards each have
flex: 1, so they share the row equally and resize as the window changes. - The
gapkeeps clean spacing without a single margin.
Try it yourself
- Reverse it. Add
flex-direction: row-reverseto.linksand watch the menu order flip. - Make one card bigger. Give the middle card
flex: 2and the othersflex: 1, then see how the space is divided. - Stack on small screens. Add
flex-wrap: wrapand amin-width: 200pxto.cardso the cards drop onto a new line when the window gets narrow.
Challenge: Build a profile card that's perfectly centered in the middle of the screen. Use a full-height container (height: 100vh) with display: flex; justify-content: center; align-items: center;, and inside it place a card containing an emoji avatar, a name and a short bio laid out in a flex-direction: column. Once it works, make it responsive using the ideas in Responsive Web Design Basics.
Quick quiz
Test yourself and earn XP
What property turns an element into a flex container?
Setting display: flex on a container makes its direct children become flex items.
What does flex-direction: column do?
flex-direction: column changes the main axis to vertical, so items stack top to bottom.
Which property spreads items out along the main axis?
justify-content controls spacing and alignment along the main axis, e.g. space-between or center.
How do you make a flex item grow to share leftover space?
flex: 1 tells the item to grow and take an equal share of the free space in the container.
What does justify-content: center do in a default row?
In a row, the main axis is horizontal, so justify-content: center centers the items left-to-right.
FAQ
Flexbox is best for laying things out in a single direction β a row of buttons, a navbar, or a column of cards. CSS Grid is better when you need rows AND columns at the same time, like a full page layout. Many sites use both: Grid for the page skeleton, Flexbox inside each section.
The most common reason is putting justify-content or align-items on the wrong element. They belong on the flex CONTAINER (the parent with display: flex), not on the children. Also check that the items are direct children β flex only affects one level down.
Keep exploring
More in Coding