Topic 8.5
Aligning in Grid
In one line
justify-* aligns along the row (inline) axis and align-* along the column (block) axis; -items and -self move items inside their grid areas, -content moves the whole set of tracks inside the container, and place-* sets both axes at once.
Think of it like this
Photos in a box of picture frames. Each photo can sit in the middle of its own frame, or in a corner, or be stretched to fill it: that's aligning an item inside its cell. Separately, if the frames don't fill the wall, you choose whether to bunch the whole group of frames in the middle of the wall or spread them out: that's aligning the tracks inside the container. Grid gives you separate controls for the two.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Inline axis
- The direction text runs in a line (left to right in English). Grid's
justify-*properties work along it. - Block axis
- The direction paragraphs stack (top to bottom). Grid's
align-*properties work along it. - `justify-items` / `align-items`
- Set on the container: where every item sits inside its own area.
- `justify-self` / `align-self`
- Set on one item: overrides the container's
-itemsvalue for that item. - `justify-content` / `align-content`
- Set on the container: where the whole group of tracks sits when they're smaller than the container.
- Stretch
- Fill the whole area in that axis. The default for grid items without a fixed size or aspect ratio.
- `place-*`
- Shorthands that set the align value and then the justify value in one go.
- `safe`
- A keyword that stops centring from pushing an oversized item out of reach; it falls back to start.
Step by step
01Know which axis you're moving
Say it aloud: justify = along the row, align = down the column. Then ask: am I moving items inside their cells (-items, -self) or all the tracks inside the container (-content)?
02Stop items stretching
By default each item fills its cell. align-items: start makes items only as tall as their content, sitting at the top of each cell; justify-items: start does the same for width.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: start;
}03Override one item
One item should sit at the bottom-right of its cell. place-self: end sets both axes to end.
.grid .note {
place-self: end;
/* align-self: end; justify-self: end; */
}04Move the tracks
With fixed 80px columns in a wide container, there's spare space. justify-content: center puts the whole group in the middle; space-between pushes the first and last tracks to the edges.
.grid {
display: grid;
grid-template-columns: repeat(3, 80px);
justify-content: space-between;
}05Centre anything in one line
A grid with one item and place-items: center centres that item horizontally and vertically, whatever its size.
.hero {
min-height: 300px;
display: grid;
place-items: center;
}Try it yourself
- 1
Predict before you align
In the first example, add
justify-self: endto.i3. Predict its newxand width: it can't stretch across any more, so it shrinks to its text width and moves to the right of its cell. Run and check which numbers changed. - 2
Try every content value
In the second example, change
justify-contenttocenter, thenspace-around, thenspace-evenly. Predict item 4'sxeach time:centergives 150 (70px each side, so 70 + 80),space-evenlygives 173.33 (the 140px splits into three gaps of 46.67). - 3
Stretch the image
In the third example, give the image's box
place-items: stretchand the imagewidth: 100%; height: 100%; object-fit: cover. Predict the logged size (200x120). Withoutobject-fitit would distort.
Code & diagrams
`i1` fills its whole 150×80 cell (stretch). `i2` is centred across its cell but still stretches vertically. `i3` stretches across but sits at the bottom. `i4` is centred both ways.
Preview
Console
Nothing logged yet.Expected console output
i1 x=0 y=0 150x80
i2 x=195 y=0 60x80
i3 x=0 y=130 150x30
i4 x=195 y=105 60x30The tracks use 160px of 300px width and 100px of 200px height. `space-between` puts the spare 140px between the two columns; `align-content: center` puts 50px above and below the rows. Try `place-content: end center`.
Preview
Console
Nothing logged yet.Expected console output
item 1 x=0 y=50
item 4 x=220 y=100`place-items: center` centres the 80×40 box. The image is **not** stretched to 200×120: elements with an aspect ratio default to `start`. The auto margins soak up the free space on the left, top and bottom.
Preview
Console
Nothing logged yet.Expected console output
.center .dot x=60 y=40 80x40
img x=0 y=0 40x40
.push x=120 y=40 80x40Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
justify-content with fr columns
On a grid with grid-template-columns: 1fr 1fr, set justify-content: center to centre the columns.
Break #2
Centring something taller than its container
In a 200px-tall panel with grid-template-rows: 200px and align-items: center, put an item that is 400px tall.
Myth vs fact
Myth
justify-* always means horizontal and align-* vertical.
Fact
In grid, justify follows the inline axis and align the block axis. In a vertical writing mode (writing-mode: vertical-rl) they swap visually.
Myth
align-content and align-items do the same thing.
Fact
align-items moves each item inside its area. align-content moves the whole set of row tracks inside the container, and only when there is spare space.
Myth
place-items: center start centres horizontally.
Fact
The first value is align (block axis), so it centres vertically and puts items at the start horizontally.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The keyword
normalis the initial value ofjustify-items,align-itemsand the-selfproperties. For grid items it computes tostretch, except for boxes with a preferred aspect ratio (images, videos,aspect-ratio), where it acts likestartso they aren't distorted. - ▸
justify-self: stretchonly affects items whose size in that axis isauto. A setwidth(ormax-width) wins. Auto margins are resolved before alignment, somargin-left: autooverridesjustify-selffor that item. - ▸
Baseline alignment (
align-items: baseline,first baseline,last baseline) groups items in the same row and aligns their text baselines, which is handy for a row of labels and inputs of different font sizes. - ▸
justify-content: space-*andgapadd up: the visible gutter isgapplus the distributed space. Items that span several tracks also grow by the distributed space inside them, so withspace-betweena spanning item can become wider than you expect.
Remember this
- 1
Grid has two axes. The inline axis runs the way text runs in a line (left to right in English): grid calls alignment along it **
justify. The block axis runs the way paragraphs stack (top to bottom): alignment along it isalign**. Unlike Flexbox, these never swap: in grid,justifyis always along the row direction andalignalways down the columns, whatever you do withgrid-auto-flow. - 2
**
justify-itemsandalign-itemsgo on the container and set the default for every item: where each item sits inside its own grid area.justify-selfandalign-selfgo on one item** and override that default. The useful values arestretch(fill the area, the default for most items),start,end,centerand, foralign-*,baseline(line up the first line of text). - 3
Stretch is why grid items fill their cells by default: the default value
normalbehaves likestretch. Two exceptions: an item with a fixedwidthorheightkeeps that size in that axis, and images and other elements with a natural aspect ratio (like<img>and<video>) behave asstartinstead, so they keep their shape. When an item doesn't stretch, it shrinks to its content size and the-selfvalue decides where in the area it sits.margin: autoon an item also works: auto margins soak up the spare space in its area and win over-self. - 4
**
justify-contentandalign-contentmove the tracks, not the items. They only do something when the tracks add up to less** than the container, for example fixed100pxcolumns in a 500px grid (with anyfrtrack the free space is already used up). Values:start,end,center,stretch(growsautotracks),space-between,space-aroundandspace-evenly. Thespace-*values make the visible gutters bigger thangap, because the extra space goes between tracks. - 5
The **
place-*shorthands set both axes at once, with thealignvalue first**:place-items: center(both centred),place-items: end start(align end, justify start). Likewiseplace-selfandplace-content.display: grid; place-items: center;on a box is the shortest way to centre one thing both ways (see Phase 6, Topic 6.5). - 6
When an item is bigger than its area, centring makes it overflow on both sides, and the part that sticks out past the top or left edge of a scroll container can never be scrolled to. The
safekeyword (align-items: safe center) tells the browser to fall back tostartwhen the item doesn't fit, so nothing is lost. Use it on centred content that might grow, like a modal's body.
Explain it without notes
Explain the difference between justify-items, justify-self and justify-content in grid.
Why do grid items fill their cells by default, and when don't they?
When does align-content have any effect?
What does place-items: end center do?
Practice
Centre a 120px by 60px button both ways inside a 100%-wide, 300px-tall hero section using grid.
A grid has three fixed 100px columns in a 600px container. Write the CSS to put equal space before, between and after the columns.
In a grid of cards where all items stretch, make only the .price item sit at the bottom-right corner of its cell.
Trade-offs
- ↔
Leaving items at
stretchgives equal-height cards for free, but backgrounds then fill the whole cell; aligning tostartkeeps boxes tight to their content at the cost of ragged bottoms. - ↔
place-items: centeris the shortest centring, but it's unsafe for content that can grow taller than its container; addsafeor use auto margins there.
Done when you can
I can tell which grid alignment properties work on the inline axis and which on the block axis.
I can align every item with
justify-items/align-itemsand one item with-self.I can move tracks with
justify-content/align-contentand say when that has an effect.I can use
place-items,place-selfandplace-content, putting the align value first.I know why images don't stretch and how
safeprevents lost content.