Command Palette

Search for a command to run...

Hectal
PHASE 7Intermediate ~29 min· topic 2 of 5

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-items for 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. baseline alignment 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.

style.csswhole filecss
.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.

Place the space on the main axisdiagram
Rendering diagram…

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.

style.csswhole filecss
.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.

style.csswhole filecss
.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.

style.csswhole filecss
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.

style.csswhole filecss
.price {
  display: flex;
  align-items: baseline;
  gap: 4px;
}
.price .amount { font-size: 40px; }
.price .per { font-size: 14px; }

Try it yourself

  1. 1

    Predict space-around for two items

    In the first example, delete one <b></b> from the space-around row. 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. 2

    Stretch the blue items

    In the second example, remove the heights from .a, .b and .c and give the items min-height values instead. Predict what stretch does now. (min-height doesn't fix the size, so the items stretch to 100px.)

  3. 3

    Swap the auto margin

    In the navbar, move margin-left: auto from Blog to Shop. Predict the new x values. (Blog follows Logo at x = 50; Shop is pushed to x = 200.)

  4. 4

    Turn off wrapping

    In the last example, change .box to flex-wrap: nowrap. Predict what align-content does now. (Nothing: one line, which fills the box. The items shrink to fit on the line instead, which Topic 7.3 explains.)

Code & diagrams

justify-content: where the free space goes New tab

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

Press Run to see the page.

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, 170
align-items: stretch only works on auto sizes New tab

The 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

Press Run to see the page.

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 0
Auto margins and align-self in a navbar New tab

The 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

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Logo: x=0 y=15
Blog: x=160 y=20
Shop: x=200 y=40
align-content spaces out wrapped lines New tab

Three 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

Press Run to see the page.

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 120

Break 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.

terminal
$ Preview
── what you'll see ──
The items move to the horizontal middle and stay stuck to the top.

Break #2

justify-content does nothing

In the first example, add .row b { flex-grow: 1; } at the end of the CSS.

terminal
$ Console
── what you'll see ──
flex-start: 0, 80, 160 (and the same for every other value)

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.

terminal
$ Preview
── what you'll see ──
The item spills out 50px on each side. The left part can't be reached, even with the scrollbar.

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/end also exist next to flex-start/flex-end. In Flexbox they differ only with reversed directions: flex-start follows the flex direction, start follows the writing mode.

  • ▸

    Overflow alignment: safe makes an item fall back to start alignment when it would overflow the container, unsafe keeps the requested alignment even when content is lost. Firefox has supported safe for years; Chromium and Safari added it for Flexbox more recently, so check support before you rely on it.

  • ▸

    align-items: baseline uses each item's first baseline; last baseline uses 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 to flex-start.

  • ▸

    Auto margins are resolved during flex layout, before justify-content. Unlike justify-content, they never push content past the start edge when space is negative, which is why margin: auto on a single child is a safe way to centre content that might overflow.

Remember this

  1. 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-content decides where that free space goes. flex-start (the default behaviour) puts it all at the end, flex-end puts it all at the start, center splits 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 and justify-content does nothing.

  2. 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-between behaves like flex-start, and the other two centre it.

  3. 3

    align-items sets the cross-axis position of every item in a line. stretch (the default; the initial value is normal, which behaves as stretch in Flexbox) makes items with an auto cross size fill the line. An item with a fixed height in a row can't stretch and sits at the start. flex-start, flex-end and center place items at the cross-start, the cross-end or the middle. baseline lines 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. 4

    align-self goes on one item and overrides align-items for it only. It takes the same values plus auto (the default, meaning "use the container's align-items"). There is no justify-self in 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. 5

    An auto margin on a flex item takes all the free space in its direction. margin-left: auto on 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: auto on the only item centres it on both axes. Auto margins are applied before justify-content, so when an auto margin exists, justify-content has no free space left to work with.

  6. 6

    align-content aligns 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 default normal behaves as stretch: the lines grow to share the extra height, which is why wrapped rows sometimes show a mysterious gap. In a container with flex-wrap: nowrap (the default) there's only one line, which always fills the container, so align-content has no effect.

Explain it without notes

01

What is free space in Flexbox, and which properties use it?

02

Explain the difference between space-between, space-around and space-evenly.

03

Why might align-items: stretch not make an item fill its container?

04

When does align-content have an effect?

05

How do you push one item to the far end of a flex row, and why does it work?

Practice

01

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.

02

Centre one .dialog box horizontally and vertically in a .overlay that fills the screen.

03

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-content can produce the same layout. Auto margins are more flexible (they can split a row into groups) and overflow safely; justify-content is easier to read when every item is treated the same.

  • ↔

    baseline gives the best-looking text rows but depends on fonts, so items move slightly when a web font loads. Use center when 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-content value 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-content does something and when it doesn't.

  • I can centre something on both axes with Flexbox.