In short
CSS Flexbox is a layout tool for arranging items in a row or a column. In this flexbox tutorial you learn display: flex, the main and cross axis, flex-direction and gap. What is CSS Flexbox?
CSS Flexbox is a layout tool for arranging items in a row or a column. In this flexbox tutorial you learn display: flex, the main and cross axis, flex-direction and gap.
What is CSS Flexbox?
Flexbox (short for "Flexible Box Layout") is a way to lay out items in one direction: either a row or a column. It makes common jobs easy that used to be hard: putting items side by side, spacing them evenly, making them the same height, and centering things.
Flexbox always works with two roles:
- The flex container – the parent element. You turn it on with
display: flex. - The flex items – the direct children of that parent. They are arranged automatically.
Think of a bookshelf. The shelf is the container, and the books are the items. You decide how the shelf arranges its books; you usually don't move each book by hand.
Note: Only direct children become flex items. Grandchildren (elements inside the items) are not affected, unless you also make their parent a flex container.
How to use display: flex
Let's start with three feature boxes. Without flexbox, <div> elements stack on top of each other, because they are block elements.
<section class="features">
<div class="feature">Fast</div>
<div class="feature">Free</div>
<div class="feature">Friendly</div>
</section>
.features {
display: flex;
gap: 16px;
padding: 16px;
background: #f3f4f6;
}
.feature {
background: white;
border: 1px solid #d1d5db;
border-radius: 8px;
padding: 20px;
font-family: system-ui, sans-serif;
}
With one line, display: flex, the three boxes now sit side by side in a row. Each box is only as wide as its content, and all boxes have the same height. The gap property adds 16 pixels of space between the items, but not on the outside edges.
You can also use display: inline-flex. It works the same inside, but the container itself acts like an inline element, so it only takes the width it needs.
Main axis vs cross axis
This is the most important idea in flexbox. A flex container has two axes (directions):
- The main axis is the direction the items flow in. By default it goes left to right, as a row.
- The cross axis runs at a right angle to the main axis. In a row, it goes top to bottom.
flex-direction | Main axis | Cross axis |
|---|---|---|
row (default) | Left to right | Top to bottom |
row-reverse | Right to left | Top to bottom |
column | Top to bottom | Left to right |
column-reverse | Bottom to top | Left to right |
Why does this matter? Almost every flexbox property works along one of these axes. justify-content works on the main axis, and align-items works on the cross axis. When you switch from row to column, the axes switch too. You will learn alignment in detail in the next lesson.
Note: In right-to-left languages like Arabic,
rowflows from right to left. Flexbox follows the writing direction of the page, which is why it talks about "start" and "end" rather than "left" and "right".
Changing direction with flex-direction
flex-direction sets which way the main axis goes. Here is a simple sidebar menu that stacks its links in a column:
<nav class="sidebar">
<a href="#">Dashboard</a>
<a href="#">My courses</a>
<a href="#">Certificates</a>
<a href="#">Settings</a>
</nav>
.sidebar {
display: flex;
flex-direction: column;
gap: 4px;
width: 200px;
padding: 12px;
background: #1f2937;
border-radius: 12px;
}
.sidebar a {
color: #e5e7eb;
text-decoration: none;
padding: 10px 14px;
border-radius: 8px;
}
.sidebar a:hover {
background: #374151;
}
The links are inline elements, but as flex items they each become a block-like box. With flex-direction: column they stack from top to bottom, each one as wide as the sidebar, with 4 pixels between them. Each link gets a soft highlight on hover.
Common mistake: Using margins on every item to create space, then fighting the extra margin on the last item. Use
gapon the container instead. It only adds space between items. You can also set two values:gap: 20px 12px;means 20px between rows and 12px between columns.
Tip: Your browser's developer tools have a flexbox inspector. Click the small "flex" badge next to the container in the Elements panel, and the browser draws the items and gaps on the page.
Practice exercise
Build a "pricing" row with three plan cards (Free, Pro, Team) side by side, using display: flex and gap. Then change the container to flex-direction: column and see how the axes switch.
Hint: change row to column in your CSS and reload the page. Notice that the cards now stretch to the full width, because the cross axis is now horizontal.
Key takeaways
display: flexturns a parent into a flex container; its direct children become flex items.- Flexbox lays out items in one direction: a row or a column.
- The main axis follows
flex-direction; the cross axis runs across it. flex-directioncan berow,row-reverse,columnorcolumn-reverse.- Use
gapfor space between items instead of margins.
Frequently asked questions
Is Flexbox better than CSS Grid?
Neither is better; they do different jobs. Flexbox is great for one direction, like a navbar or a row of buttons. Grid is great for two directions, rows and columns at once, like a full page layout. Most sites use both.
Does gap work with flexbox in all browsers?
Yes. The gap property has worked with flexbox in all modern browsers for several years, so you can use it safely.
Why are my flex items all the same height?
That is the default behaviour. Flex items stretch to fill the cross axis, because align-items starts as stretch. You can change it with align-items: flex-start.