Topic 7.2
Aligning with Flexbox
In one line
justify-content shares out leftover space along the main axis, align-items places every item on the cross axis (with align-self to override one item), and align-content spaces out whole lines when items wrap; auto margins push items apart by eating free space.
Think of it like this
Arranging photos on a shelf. You can push them all to the left end, to the right end, or into the middle. You can put the same gap between every photo, or put one photo at each end and spread the rest. That's along the shelf (the main axis). Separately, each photo can stand on the shelf, hang from the shelf above, or float in the middle of the space: that's across the shelf (the cross axis). Flexbox gives you one property for each direction.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Free space
- The length left over on an axis after all items have been sized. Alignment properties decide where it goes.
- `justify-content`
- A container property that places items along the main axis by sharing out the free space.
- `align-items`
- A container property that places every item on the cross axis inside its line.
- `align-self`
- An item property that overrides
align-itemsfor that one item. - `align-content`
- A container property that places whole lines on the cross axis when items wrap.
- Stretch
- Growing an item's cross size so it fills the line. Only works when that size is
auto. - Baseline
- The invisible line that letters sit on.
baselinealignment lines these up across items. - Auto margin
- A margin set to
auto. In Flexbox it takes all the free space on its side, pushing the item away.
Step by step
01Work out the free space
A container is 240px wide and holds three items, each 40px wide. The items use 120px, so 120px is free. Every justify-content value is only a different way of placing those 120px.
.row {
display: flex;
width: 240px;
}
.row > div {
width: 40px; /* 3 x 40 = 120, so 120px is free */
}02Place the space on the main axis
center puts 60px before the first item and 60px after the last. space-between puts 60px in each of the two gaps. space-around gives each item 20px on each side: 20px at the ends and 40px between items. space-evenly makes four equal gaps of 30px.
03Place items on the cross axis
Give the container a height and try align-items. Items with a fixed height move to the top, middle or bottom. Items with no height stretch with stretch, and shrink back to their content with every other value.
.row {
display: flex;
height: 100px;
align-items: center; /* every item in the vertical middle */
}04Override one item
align-self on one item changes only that item's cross-axis position. Here every item is centred except the badge, which drops to the bottom.
.row { align-items: center; }
.badge { align-self: flex-end; }05Push items apart with an auto margin
To put a logo on the left and links on the right, give the first link margin-left: auto. Its margin swallows all the free space, so the links are pushed to the far edge. Use margin-inline-start: auto for a version that also works right to left.
nav { display: flex; align-items: center; }
nav .push { margin-left: auto; }06Line up text with baseline
When items have different font sizes, center lines up their boxes but the text looks uneven. baseline lines up the text itself, so a big price and a small "/month" read as one line.
.price {
display: flex;
align-items: baseline;
gap: 4px;
}
.price .amount { font-size: 40px; }
.price .per { font-size: 14px; }Try it yourself
- 1
Predict space-around for two items
In the first example, delete one
<b></b>from thespace-aroundrow. Predict the two x positions before you run it. (Free space is 160px; each item gets 40px on each side, so 40 and 160.) - 2
Stretch the blue items
In the second example, remove the heights from
.a,.band.cand give the itemsmin-heightvalues instead. Predict whatstretchdoes now. (min-heightdoesn't fix the size, so the items stretch to 100px.) - 3
Swap the auto margin
In the navbar, move
margin-left: autofrom Blog to Shop. Predict the new x values. (Blog follows Logo at x = 50; Shop is pushed to x = 200.) - 4
Turn off wrapping
In the last example, change
.boxtoflex-wrap: nowrap. Predict whatalign-contentdoes now. (Nothing: one line, which fills the box. The items shrink to fit on the line instead, which Topic 7.3 explains.)
Code & diagrams
Each line prints the x position of the three items. Free space is 240 - 3 x 40 = 120px. Compare `space-around` (20px at the ends, 40px between) with `space-evenly` (30px everywhere).
Preview
Console
Nothing logged yet.Expected console output
flex-start: 0, 40, 80
flex-end: 120, 160, 200
center: 60, 100, 140
space-between: 0, 100, 200
space-around: 20, 100, 180
space-evenly: 30, 100, 170The blue items have fixed heights, so `stretch` leaves them at the top. The pink item has no height: it stretches to 100px with `stretch` and collapses to 0 (its empty content) with the other values. The `body` is a flex container too, which puts the four demos side by side.
Preview
Console
Nothing logged yet.Expected console output
stretch: tops 0,0,0 | pink height 100
flex-start: tops 0,0,0 | pink height 0
center: tops 40,30,20 | pink height 0
flex-end: tops 80,60,40 | pink height 0The auto margin on Blog takes the 110px of free space, so Blog and Shop sit at the right end. Logo (30px tall) and Blog (20px) are centred; Shop uses `align-self: flex-end` and sits at the bottom (60 - 20 = 40).
Preview
Console
Nothing logged yet.Expected console output
Logo: x=0 y=15
Blog: x=160 y=20
Shop: x=200 y=40Three 60px items fit on each 200px line, so six items make two lines, each 30px tall, with 90px of spare height. With the default (`normal`, which acts as `stretch`) each line grows to 75px, so line 2 starts at 75 and a gap appears under line 1.
Preview
Console
Nothing logged yet.Expected console output
normal: line 1 at 0, line 2 at 75
flex-start: line 1 at 0, line 2 at 30
center: line 1 at 45, line 2 at 75
space-between: line 1 at 0, line 2 at 120Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Use justify-content to centre vertically
In a flex-direction: row container 100px tall, try to centre the items vertically with justify-content: center.
Break #2
justify-content does nothing
In the first example, add .row b { flex-grow: 1; } at the end of the CSS.
Break #3
Centre content that's bigger than its container
Put a 300px-wide item in a 200px container with justify-content: center and overflow: auto.
Myth vs fact
Myth
align-items aligns horizontally and justify-content vertically (or the other way round).
Fact
They are tied to axes, not directions. justify-content is the main axis, align-items the cross axis. Which one is horizontal depends on flex-direction.
Myth
align-content is a stronger version of align-items.
Fact
It aligns whole lines in a wrapping container. On a single-line container (flex-wrap: nowrap) it does nothing.
Myth
You need justify-self to move one item along the main axis.
Fact
Flexbox ignores justify-self. Use an auto margin on the item instead.
Myth
space-around gives equal gaps.
Fact
Equal space around each item, so the inner gaps are twice the outer ones. space-evenly gives equal gaps.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The alignment properties come from the CSS Box Alignment module, shared by Flexbox, Grid and (for some properties) block layout. That's why
start/endalso exist next toflex-start/flex-end. In Flexbox they differ only with reversed directions:flex-startfollows the flex direction,startfollows the writing mode. - ▸
Overflow alignment:
safemakes an item fall back to start alignment when it would overflow the container,unsafekeeps the requested alignment even when content is lost. Firefox has supportedsafefor years; Chromium and Safari added it for Flexbox more recently, so check support before you rely on it. - ▸
align-items: baselineuses each item's first baseline;last baselineuses the last line of text. Items that can't take part in baseline alignment (for example, when the baseline is on the other axis in a column) fall back toflex-start. - ▸
Auto margins are resolved during flex layout, before
justify-content. Unlikejustify-content, they never push content past the start edge when space is negative, which is whymargin: autoon a single child is a safe way to centre content that might overflow.
Remember this
- 1
Free space is the key idea. After the browser has sized every item, whatever length is left over on the main axis is free space.
justify-contentdecides where that free space goes.flex-start(the default behaviour) puts it all at the end,flex-endputs it all at the start,centersplits it equally before the first and after the last item. If the items have grown to fill the line (Topic 7.3), there is no free space andjustify-contentdoes nothing. - 2
The three space values hand the free space out between items.
space-between: first item at main-start, last at main-end, equal gaps between them.space-around: every item gets equal space on both sides, so the gap between two items is twice the gap at the ends.space-evenly: every gap, including the two ends, is exactly equal. With one item,space-betweenbehaves likeflex-start, and the other two centre it. - 3
align-itemssets the cross-axis position of every item in a line.stretch(the default; the initial value isnormal, which behaves asstretchin Flexbox) makes items with an auto cross size fill the line. An item with a fixedheightin a row can't stretch and sits at the start.flex-start,flex-endandcenterplace items at the cross-start, the cross-end or the middle.baselinelines items up so the baselines (the invisible line letters sit on) of their first lines of text match, which is what you want when items have different font sizes. - 4
align-selfgoes on one item and overridesalign-itemsfor it only. It takes the same values plusauto(the default, meaning "use the container'salign-items"). There is nojustify-selfin Flexbox: an item can't be moved alone on the main axis with a property, because the main axis is shared by all items in the line. To push one item away, use an auto margin. - 5
An auto margin on a flex item takes all the free space in its direction.
margin-left: autoon the last link of a navbar eats the free space to its left, so it and everything after it move to the right edge.margin: autoon the only item centres it on both axes. Auto margins are applied beforejustify-content, so when an auto margin exists,justify-contenthas no free space left to work with. - 6
align-contentaligns lines, not items. It only matters when items wrap onto several lines (flex-wrap: wrap, Topic 7.4) and the container is taller than the lines need. Its defaultnormalbehaves asstretch: the lines grow to share the extra height, which is why wrapped rows sometimes show a mysterious gap. In a container withflex-wrap: nowrap(the default) there's only one line, which always fills the container, soalign-contenthas no effect.
Explain it without notes
What is free space in Flexbox, and which properties use it?
Explain the difference between space-between, space-around and space-evenly.
Why might align-items: stretch not make an item fill its container?
When does align-content have an effect?
How do you push one item to the far end of a flex row, and why does it work?
Practice
A footer row holds a copyright <p> and a <ul> of links. Put the copyright on the left and the links on the right, vertically centred.
Centre one .dialog box horizontally and vertically in a .overlay that fills the screen.
A .price row shows <span class="amount">₹499</span><span class="per">/month</span> in two font sizes. Line up the text so both parts sit on the same line.
Trade-offs
- ↔
Auto margins and
justify-contentcan produce the same layout. Auto margins are more flexible (they can split a row into groups) and overflow safely;justify-contentis easier to read when every item is treated the same. - ↔
baselinegives the best-looking text rows but depends on fonts, so items move slightly when a web font loads. Usecenterwhen the items are icons or boxes without text.
Done when you can
I can work out the free space in a flex line and say where each
justify-contentvalue puts it.I can align items on the cross axis, and know why a fixed size stops
stretch.I can override one item with
align-self.I can push items apart with an auto margin.
I know when
align-contentdoes something and when it doesn't.I can centre something on both axes with Flexbox.