DevPath · Learn to code ESPTEN

CSS Grid

Placing items: lines, span and areas

The grid lines

Here's the number-one confusion with Grid: you count the lines, not the cells. A grid of N columns has N+1 vertical lines, numbered from 1. Three columns are delimited by lines 1, 2, 3 and 4 (four lines for three gaps, like the posts of a fence). An item is placed by stating between which lines it starts and ends.

.featured {
  grid-column: 1 / 3;   /* from line 1 to line 3: spans 2 columns */
  grid-row: 1 / 2;      /* from line 1 to line 2: one row */
}

span: occupy several cells

If you don't want to count lines, use the keyword span to state how many tracks to occupy starting from where the item begins:

.featured {
  grid-column: span 2;  /* spans 2 columns, wherever it starts */
  grid-row: span 2;     /* and 2 rows */
}

This is perfect for that "featured photo" that fills half the gallery, without tying yourself to specific positions: reorder the cards and the featured one keeps its size without you touching a single line number.

⚠️ CLASSIC TRAP: span 2 isn't "go to line 2", it's "occupy 2 tracks". If you mix grid-column: 2 / span 2 it counts from line 2 and moves forward 2 slots. Don't confuse the line number with the number of cells to occupy.

Named areas: the visual layout

The most readable way to lay out a page is to draw it with grid-template-areas. You define the grid as a "map" of names and then assign each item to its zone with grid-area:

.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "menu   content"
    "footer footer";
  gap: 12px;
}

.header  { grid-area: header; }
.menu    { grid-area: menu; }
.content { grid-area: content; }
.footer  { grid-area: footer; }

The repeated name (header header) makes that zone span several columns. A dot (.) leaves a cell empty. The big advantage: the CSS reads like an ASCII drawing of the page, and to change the whole layout you only rewrite the map.

⚠️ CLASSIC TRAP: the "map" must be a perfect rectangle. Every row needs the same number of columns, and each area has to form a rectangular block (no L-shaped zones). If one row is missing a name, the whole rule is silently ignored and you'll go crazy hunting for the bug.

Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Basic grid: rows, columns and the fr unitResponsive without media queries: auto-fit and minmax →