CSS course menu
CSS Flexbox: A Complete Beginner's Guide with Examples
Learn CSS Flexbox with live examples: flex containers and items, flex-direction, main and cross axes, justify-content, align-items, flex-wrap, gap, align-content, and common layouts such as navbars, card rows and sticky footers.
On this page
Flexbox (the flexible box layout) arranges items in one direction, a row or a column, and controls how they are spaced, aligned and sized. It is the go-to tool for navigation bars, toolbars, card rows, form rows and centering.
A flex container#
Setting display: flex on an element makes it a flex container and its direct children flex items:
.row { display: flex; gap: 8px; padding: 8px; background: #eef3ff; }
.row div { padding: 12px 16px; background: #2f5fe0; color: white; border-radius: 6px; }<div class="row">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>The divs, normally stacked as blocks, now sit in a row, as wide as their content, with gap between them.
Two axes#
Flexbox works along two axes:
- The main axis is the direction items are placed in, set by
flex-direction. - The cross axis runs perpendicular to it.
justify-content aligns along the main axis. align-items aligns along the cross axis. Keeping these two straight is most of Flexbox.
justify-content: the main axis#
.row { display: flex; padding: 6px; margin-bottom: 8px; background: #eef3ff; font: 12px monospace; }
.row span { padding: 8px 12px; background: #2f5fe0; color: white; border-radius: 4px; }<div class="row" style="justify-content: flex-start"><span>flex-start</span><span>B</span><span>C</span></div>
<div class="row" style="justify-content: center"><span>center</span><span>B</span><span>C</span></div>
<div class="row" style="justify-content: flex-end"><span>flex-end</span><span>B</span><span>C</span></div>
<div class="row" style="justify-content: space-between"><span>space-between</span><span>B</span><span>C</span></div>
<div class="row" style="justify-content: space-around"><span>space-around</span><span>B</span><span>C</span></div>
<div class="row" style="justify-content: space-evenly"><span>space-evenly</span><span>B</span><span>C</span></div>align-items: the cross axis#
.row { display: flex; gap: 6px; height: 80px; padding: 6px; margin-bottom: 8px; background: #fff3c4; font: 12px monospace; }
.row span { padding: 6px 10px; background: #e8590c; color: white; border-radius: 4px; }
.row span:nth-child(2) { padding: 18px 10px; }<div class="row" style="align-items: stretch"><span>stretch (default)</span><span>tall</span></div>
<div class="row" style="align-items: flex-start"><span>flex-start</span><span>tall</span></div>
<div class="row" style="align-items: center"><span>center</span><span>tall</span></div>
<div class="row" style="align-items: flex-end"><span>flex-end</span><span>tall</span></div>By default (stretch), items stretch to the full height of the row, which is why flex columns in a row are automatically equal height.
Columns#
With flex-direction: column, the axes swap: justify-content now works vertically and align-items horizontally:
.col {
display: flex;
flex-direction: column;
align-items: center; /* horizontal, because the cross axis is now horizontal */
gap: 6px;
padding: 10px;
background: #e6f5f3;
}
.col span { padding: 8px 14px; background: #0f8a7e; color: white; border-radius: 6px; }<div class="col"><span>Sign in</span><span>Create an account</span><span>Help</span></div>Wrapping#
By default, flex items all stay on one line and shrink to fit. flex-wrap: wrap lets them move onto new lines:
.tags { display: flex; flex-wrap: wrap; gap: 6px; max-width: 320px; }
.tags span { padding: 4px 10px; border: 1px solid #2f5fe0; border-radius: 999px; color: #2f5fe0; }<div class="tags">
<span>html</span><span>css</span><span>javascript</span><span>flexbox</span>
<span>grid</span><span>responsive</span><span>accessibility</span><span>performance</span>
</div>When lines wrap, align-content controls the spacing between the lines (it has no effect on a single line).
Common patterns#
A navigation bar#
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 16px;
background: #1d3b4f;
color: white;
font-family: system-ui, sans-serif;
}
.navbar nav { display: flex; gap: 16px; }
.navbar a { color: white; text-decoration: none; }<header class="navbar">
<strong>Laviyx</strong>
<nav><a href="#">Courses</a><a href="#">Practice</a><a href="#">About</a></nav>
</header>Pushing one item to the end#
An auto margin absorbs all the free space, pushing an item (and everything after it) away:
.bar { display: flex; gap: 8px; padding: 8px; background: #f1f3f5; }
.bar button { padding: 6px 12px; }
.bar .end { margin-left: auto; }<div class="bar">
<button>Bold</button><button>Italic</button>
<button class="end">Save</button>
</div>A footer that stays at the bottom#
body { min-height: 100dvh; display: flex; flex-direction: column; }
main { flex: 1; } /* main grows to fill the space, pushing the footer down */flex: 1 is explained in Flex Items: grow, shrink and basis.
Practice#
Practice exercise
Build a card row: three cards side by side with 16px gaps that wrap onto new lines on narrow screens, where each card has equal height and its "Read more" link sits at the bottom of the card.
Show solution
.cards { display: flex; flex-wrap: wrap; gap: 16px; }
.card {
flex: 1 1 180px; /* grow, shrink, start at 180px: see the next lesson */
display: flex;
flex-direction: column;
padding: 12px;
border: 1px solid #ddd;
border-radius: 10px;
}
.card a { margin-top: auto; }<div class="cards">
<article class="card"><h3>HTML</h3><p>Structure.</p><a href="#">Read more</a></article>
<article class="card"><h3>CSS</h3><p>Presentation, layout, colours, fonts and animation, which takes a few more words.</p><a href="#">Read more</a></article>
<article class="card"><h3>JavaScript</h3><p>Behaviour.</p><a href="#">Read more</a></article>
</div>The row stretches all cards to the same height; inside each card, a column flexbox with margin-top: auto on the link pushes it to the bottom.
Key takeaway#
Finished this lesson?