Command Palette

Search for a command to run...

Hectal
PHASE 8Intermediate ~29 min· topic 3 of 6

Topic 8.3

Placing Items

In one line

You place a grid item by naming the lines it starts and ends on (grid-column: 1 / 3), by saying how many tracks it spans (span 2), or by counting from the end with negative numbers (1 / -1); items may overlap, and later items or a higher z-index paint on top.

Think of it like this

A school timetable. The days are columns and the periods are rows. A double maths lesson starts at period 2 and ends before period 4: it covers two boxes. Lunch spans every day, from the first column to the last. You describe each lesson by where it starts and where it ends, and that's exactly how you place a grid item.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Line number
The number of a grid line, counting from 1 at the start. A grid with N tracks has N + 1 lines.
`grid-column` / `grid-row`
Shorthands for where an item starts and ends: grid-column: 1 / 3.
`grid-area` (placement)
All four lines at once: row-start / column-start / row-end / column-end.
`span`
How many tracks an item covers, instead of naming its end line: span 2.
Negative line
A line counted from the end of the explicit grid: -1 is the last line.
Overlap
Two or more items covering the same cells. The later or higher z-index one shows on top.
Named line
A grid line given a name in square brackets, like [content-start], so you can place items by name.
`z-index`
A number that decides which overlapping item is drawn on top. Higher is closer to you.

Step by step

01Count the lines first

Draw the grid in your head and number its lines. Four equal columns give column lines 1, 2, 3, 4, 5. The last line is also -1, the first is also -5.

Count the lines firstdiagram
Rendering diagram…

02Place an item by start and end

The header covers columns 1 to 4: it starts on line 1 and ends on line 5. 1 / -1 says the same thing and keeps working if you add a column later.

style.csswhole filecss
.header {
  grid-column: 1 / -1;
}

03Let an item span without fixing its position

A featured photo should be twice as big, but you don't care where it lands. span 2 in both directions makes it a 2 by 2 block; auto-placement finds the first free spot that fits.

style.csswhole filecss
.featured {
  grid-column: span 2;
  grid-row: span 2;
}

04Use grid-area for all four lines

grid-area: 2 / 1 / 4 / 3 is row 2 to 4, column 1 to 3. Read it as top / left / bottom / right.

style.csswhole filecss
.sidebar {
  grid-area: 2 / 1 / 4 / 3;
  /* same as: grid-row: 2 / 4; grid-column: 1 / 3; */
}

05Overlap two items

Put the photo and the caption in the same cells. The caption comes later in the HTML, so it's drawn on top. Give it align-self: end (Topic 8.5) to sit at the bottom of the photo.

style.csswhole filecss
.hero { display: grid; }
.hero img,
.hero .caption {
  grid-area: 1 / 1;
}
.hero .caption {
  align-self: end;
}

06Name lines for readable placement

A common article layout: text stays in a readable middle column, but images can break out to full width. Named lines make the intention obvious.

style.csswhole filecss
.article {
  display: grid;
  grid-template-columns:
    [full-start] 1fr [content-start] minmax(0, 60ch) [content-end] 1fr [full-end];
}
.article > * { grid-column: content; }
.article > .wide { grid-column: full; }

Try it yourself

  1. 1

    Move c up

    In the first example, change .c to grid-column: 2 / -1; grid-row: 2;. Predict whether anything changes (no: it was already in row 2). Now change it to grid-row: 1. Predict where a, b and d go, then check: placed items go first, so c takes row 1 and the others flow around it.

  2. 2

    Switch to grid-area

    Rewrite .a as one grid-area declaration that keeps it in row 1, columns 1 to 2. (Answer: grid-area: 1 / 1 / 2 / 3.) Run: the console line for a should be the same.

  3. 3

    Move the badge

    In the second example, move the badge to the bottom-left cell with grid-area: 2 / 1. Predict which is on top at the badge now: the badge or the caption? (The badge, because of its z-index.)

Code & diagrams

Line numbers, span and negative lines New tab

`b` lands right after `a` because auto-placement moves forward. `c` must start on line 2, which is already used in row 1, so it drops to row 2. `d` has no free cell left in row 2 (the cursor is past `c`), so it starts row 3.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

a 1 / 3 x=0 y=0 w=200
b span 2 / auto x=200 y=0 w=200
c 2 / -1 x=100 y=40 w=300
d auto / auto x=0 y=80 w=100
Overlapping items and z-index New tab

The caption is later in the HTML than the photo, so it's on top. The badge comes **first** in the HTML, so it would be hidden under the photo, but `z-index: 1` lifts it. Delete the `z-index` line and run: the badge disappears behind the photo.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

at the centre of .caption the top element is caption
at the centre of .badge the top element is badge
photo grid-area: 1 / 1 / 3 / 3
Named lines and lines outside the grid New tab

`grid-column: content` uses the lines named `content-start` and `content-end`. In the small grid, `column 5` doesn't exist, so the browser adds two 30px implicit columns. `1 / -1` still spans only the three explicit columns (150px).

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

text width: 240 wide width: 300
small grid tracks: 50px 50px 50px 30px 30px
1 / -1 width: 150
How the browser places itemsdiagram
Rendering diagram…

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

Count tracks instead of lines

To make a header cover all 3 columns, write grid-column: 1 / 3.

terminal
$ the page shows
── what you'll see ──
The header covers only the first two columns; the third cell of row 1 is filled by the next item.

Break #2

Expect -1 to reach implicit columns

In a grid with no grid-template-columns and grid-auto-flow: column, give a heading grid-column: 1 / -1.

terminal
$ the page shows
── what you'll see ──
The heading covers only the first column instead of the whole row.

Break #3

Visual order that fights the HTML

Reorder a form's fields visually by placing the last input in row 1 with grid-row: 1.

terminal
$ keyboard test
── what you'll see ──
Pressing Tab jumps from the bottom field to the top one: focus follows the HTML, not the picture.

Myth vs fact

Myth

grid-column: 1 / 3 covers three columns.

Fact

It covers two: from line 1 to line 3. The end number is a line, not a count.

Myth

z-index only works with position: relative or absolute.

Fact

Grid items (and flex items) are stacked by z-index even when they are position: static.

Myth

Placing an item on a line that doesn't exist hides it.

Fact

The browser adds implicit tracks so the line exists, and the item shows up there.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    The placement algorithm runs in a fixed order: items with a definite row and column, then items locked to a row, then the implicit grid's columns are settled, then the rest are auto-placed with a cursor. In sparse mode the cursor only moves forward, which is why item d above skipped the free cell at row 2, column 1.

  • ▸

    When you place with a name that appears several times (repeat(3, [col] 1fr)), grid-column: col 2 means "the second line named col". span col 2 spans until the second such line. If the name doesn't exist at all, every implicit line is assumed to have it, which can create surprising implicit tracks.

  • ▸

    Overlapping grid items create stacking order from z-index and DOM order without needing positioning. A grid item with a z-index other than auto also creates a stacking context, like a positioned element, so its children can't escape above a sibling item (Phase 6, Topic 6.3).

  • ▸

    order (shared with Flexbox) changes auto-placement order and painting order but not focus order. CSS Display Level 4's reading-flow property, now shipping in Chromium, lets the browser follow the visual grid order for focus and screen readers; until it is supported everywhere, keep the HTML in a sensible order.

Remember this

  1. 1

    Every item has four placement properties: **grid-column-start, grid-column-end, grid-row-start and grid-row-end. Each takes a line number**. grid-column-start: 2; grid-column-end: 4; means "start on column line 2, end on column line 4": the item covers columns 2 and 3. Remember you count lines, not tracks: a 4-column grid has lines 1 to 5.

  2. 2

    The shorthands are **grid-column and grid-row**, written as start / end: grid-column: 2 / 4 and grid-row: 1 / 3. If you give only one number (grid-column: 2), the item starts there and spans one track. **grid-area is the shortest form, with four values in the order row-start / column-start / row-end / column-end** (top, left, bottom, right: the opposite of the clockwise order of margin).

  3. 3

    **span** describes size instead of an end line: grid-column: span 2 means "cover two columns, wherever auto-placement puts me", and grid-column: 3 / span 2 means "start on line 3 and cover two columns". Spans are perfect for galleries where some pictures are bigger, because you don't have to know where they will land.

  4. 4

    Negative numbers count from the end of the explicit grid: -1 is the last line, -2 the one before. So grid-column: 1 / -1 stretches an item across the whole explicit grid however many columns there are: the standard way to write a full-width banner or a heading row. Careful: negative numbers count only the explicit grid (the tracks you wrote), not implicit tracks the browser added.

  5. 5

    If you place an item on a line that doesn't exist (grid-column: 7 in a 3-column grid), the browser does not clip it. It adds implicit columns (sized by grid-auto-columns) so the line exists. Items you place explicitly are put first; then auto-placement fills the remaining cells around them in order. An item with only a column given is put in the first row where those columns are free.

  6. 6

    Items can overlap: give two items the same lines and they share the cells. By default the one later in the HTML paints on top. **z-index works on grid items without** position: relative (unlike normal blocks, Phase 6), so z-index: 1 lifts an item above its neighbours. Overlap is how you put a caption over a photo without absolute positioning: both items stay in the grid and both affect the track sizes.

  7. 7

    You can also name lines inside the template with square brackets: grid-template-columns: [full-start] 1rem [content-start] 1fr [content-end] 1rem [full-end]. Then grid-column: content-start / content-end is easier to read than 2 / 3, and names ending in -start and -end let you write grid-column: content for short. A line can have several names, like [sidebar-end main-start].

Explain it without notes

01

Explain the difference between grid-column: 2 / 4 and grid-column: 2 / span 2, and when you'd use span alone.

02

What does grid-column: 1 / -1 do, and when doesn't it reach the last visible column?

03

In what order does grid-area: 1 / 2 / 3 / 4 give its four lines?

04

How can two grid items overlap, and how do you control which one is on top?

Practice

01

In a 3-column grid, make the first item a full-width header and the last item a full-width footer, whatever the number of columns.

02

Make the featured photo in a 4-column gallery cover two columns and two rows, starting in the top-left corner.

03

Put a text label over the bottom of an image using grid overlap, with no position: absolute.

Trade-offs

  • ↔

    Explicit line numbers give exact control but break when you add or remove a column; span, -1 and named lines survive template changes better.

  • ↔

    Overlapping grid items keep everything in layout (both items size the track) unlike absolute positioning, but the overlap is purely visual; make sure text over images has enough contrast.

Done when you can

  • I can place an item with grid-column, grid-row and grid-area, counting lines correctly.

  • I can use span and negative lines like 1 / -1.

  • I can predict where auto-placed items go around explicitly placed ones.

  • I can overlap items and control which is on top with z-index.

  • I can name lines and place items by name.