Step 1: semantic markup
Every layout starts with meaning, as lesson 3-3 established, rather than with looks.
<header class="site-header"> <a class="logo" href="/">Hack U</a> <nav class="site-nav"> <a href="/courses">Courses</a> <a href="/dsa">DSA</a> <a href="/apply">Apply</a> </nav> </header>
| Element | Default display | Result unstyled |
|---|---|---|
header | block | full-width band |
nav | block | drops below the logo |
a | inline | links sit on one line |
Unstyled, this renders awkwardly, with the nav on its own line below the logo. Flexbox fixes it at two levels, which is the point of the next step.
Step 2: two flex containers
.site-header {
display: flex;
justify-content: space-between; /* logo left, nav right */
align-items: center; /* vertical centering */
padding: 12px 24px;
}
.site-nav {
display: flex;
gap: 24px; /* even spacing between links */
}| Container | Its flex items | Job |
|---|---|---|
.site-header | the logo and the nav | push them to opposite ends |
.site-nav | the three links | space them evenly |
Read with the axis model from lesson 6-1, the header pushes logo and nav to opposite ends of its main axis, and the nav is itself a flex container spacing its links with gap.
Nesting flex containers like this is how most real headers, cards, and toolbars are built. The nav is simultaneously an item of the outer container and a container for its own children, which is the composition that makes flexbox scale.
One more line helps on small screens, since flex-wrap: wrap; lets items break onto a second line instead of overflowing.
The most common layout on the web
A logo on the left, navigation on the right, both vertically centered.
CSS
body { font-family: sans-serif; margin: 0; }
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
border-bottom: 2px solid #d4af37;
}
.site-nav {
display: flex;
gap: 24px;
}
.logo { font-weight: bold; text-decoration: none; color: black; }
.site-nav a { text-decoration: none; color: black; }| Selector | Declarations that matter | Effect |
|---|---|---|
.site-header | display: flex, justify-content: space-between, align-items: center | logo and nav at opposite ends, centered |
.site-nav | display: flex, gap: 24px | links in a row, evenly spaced |
space-between pushes the first and last children to opposite ends and puts all the leftover space between them, while align-items: center lines them up on the same invisible middle line.
If the links still stack vertically, the missing declaration is display: flex on .site-nav. That is the single most common cause, because the outer container being flex says nothing about how its children lay out their own contents.
What space-between does in the header
In .site-header, justify-content: space-between pins the logo to the left edge and the nav to the right edge.
With exactly two flex items, space-between pushes them to opposite ends of the main axis, which is exactly the logo-left, menu-right shape of most sites.
| Item count | Where the space goes |
|---|---|
| two | all of it between the pair |
| three | split into two equal gaps |
The 24px between individual links comes from the nav's own gap rather than from the header, which is the practical payoff of nesting the two containers.
Letting items wrap
The container property that lets flex items break onto a new line is flex-wrap: wrap.
By default a flex row squeezes everything onto one line, shrinking items or overflowing the container. With wrapping enabled, items that no longer fit move to the next line.
| Value | Behavior when items do not fit |
|---|---|
nowrap | stay on one line, shrink or overflow |
wrap | move onto new lines |
The property name says exactly what the items do, which makes it easy to remember. On a nav with many links it is often the only change needed to make a header usable on a phone.