Line-Based Positioning in CSS Grid

Line-based placement is the foundation for positioning items in CSS Grid. Whether you end up using named areas or auto-placement, those features ultimately build on the grid of numbered lines that your tracks create. This article covers everything you need to know about placing items directly against those lines.

You position an item by specifying the line where it starts and the line where it ends. On a five-column, five-row grid, placing an item across the second and third column tracks and the first through third row tracks looks like this:

.item {
  grid-column-start: 2;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 4;
}

You can condense this with the grid-column and grid-row shorthands, where the value before the slash is the start line and the value after is the end line:

.item {
  grid-column: 2 / 4;
  grid-row: 1 / 4;
}

See the Pen Grid Lines: placement shorthands by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: placement shorthands by Rachel Andrew (@rachelandrew) on CodePen.

The item's background stretches across the entire area because the initial values of align-self and justify-self are stretch.

If an item only needs to occupy one track, you can drop the end line. Auto-placed items default to a single column and row track, so this is common:

.item {
  grid-column: 2 / 3;
}

Leaving the end line off is equally valid:

.item {
  grid-column: 2;
}

Setting All Four Lines with grid-area

The grid-area property can set all four placement lines at once:

.item {
  grid-area: 1 / 2 / 4 / 4;
}

The order is grid-row-start, grid-column-start, grid-row-end, grid-column-end. In a left-to-right horizontal language, that maps to top, left, bottom, right — the reverse of shorthands like margin, which run top, right, bottom, left.

The reason for this ordering is that grid works identically regardless of writing mode or script direction. Setting both start lines followed by both end lines makes more sense than implying physical screen dimensions. In practice, the two-value grid-column and grid-row shorthands are often easier to scan.

Numbering on the Explicit and Implicit Grid

The explicit grid is the one you define with grid-template-columns and grid-template-rows. These track definitions also create the lines between and around them, numbered starting from 1 at the start edge in both the block and inline directions.

Item is shown in position with the Firefox Grid Inspector highlighting the lines
The item placed on the grid

In a horizontal RTL writing mode, line 1 in the block direction stays at the top, but line 1 in the inline direction moves to the right:

The item is now placed from the right-hand side of the grid
The same placement with direction: rtl

With a vertical writing mode like vertical-rl, line 1 in the block direction starts on the right, and line 1 in the inline direction is at the top:

The entire grid is now rotated 90 degrees
The same placement in writing-mode: vertical-rl

Grid lines are therefore always relative to writing mode and script direction, not to physical dimensions.

The last line of the explicit grid is always numbered -1, with lines counting backwards from there. To span an item across every track of the explicit grid:

.item {
  grid-column: 1 / -1;
}

Implicit grid tracks also number up from 1. However, negative line numbers only resolve against the explicit grid. In the example below, columns are explicit but rows are implicit, sized at 5em via grid-auto-rows. Placing an item from row line 1 to line -1 resolves to row line 2, not the final row line, because the implicit grid has no -1 reference:

See the Pen Grid Lines: explicit vs. implicit grid by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: explicit vs. implicit grid by Rachel Andrew (@rachelandrew) on CodePen.

There is currently no way to target the last line of the implicit grid without knowing how many lines exist.

Using Named Lines

You can give lines names by placing them in square brackets between track sizes in grid-template-columns and grid-template-rows:

.grid {
  display: grid;
  grid-template-columns: [full-start] 1fr [main-start] 2fr 2fr [main-end full-end];
}

Those names can replace line numbers when positioning items:

.item {
  grid-column: main-start / main-end;
}

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

If a line has multiple names, any of them resolve to the same line, so you can pick whichever is most descriptive for the context.

Repeated Names with repeat()

When you use the same line name multiple times — for example, inside repeat() — the name acts as an index. In an 8-column grid created by repeating 1fr 2fr four times, naming the line before the smaller track sm and the larger track lg produces four lines with each name. To start at the second sm line and end at the third lg line:

grid-column: sm 2 / lg 3;

Using a name without a number always resolves to the first line with that name.

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

Spanning Tracks with the span Keyword

The span keyword is for cases where you know how many tracks an item should occupy but not where it will land. This often matters with auto-placement. Starting on line auto (the line auto-placement would pick) and spanning three tracks looks like this:

.item {
  grid-column: auto / span 3;
}

See the Pen Grid Lines: span keyword by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: span keyword by Rachel Andrew (@rachelandrew) on CodePen.

This becomes particularly useful with the subgrid value for grid-template-columns and grid-template-rows. In a card layout where headers and content areas should align across cards, each card can span two rows while auto-placement still determines card order. Each card then uses subgrid to get its two internal rows:

See the Pen Grid Lines: span keyword and subgrid by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: span keyword and subgrid by Rachel Andrew (@rachelandrew) on CodePen.
The example in Firefox using the Grid Inspector

Overlaying Items on the Same Lines

Auto-placement never stacks items into the same cell — it always looks for empty space. Line-based placement is the way to layer items. In the example below, an image spans two row tracks, and a caption sits in the second track with a semi-transparent background:

See the Pen Grid Lines: card with layered elements by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: card with layered elements by Rachel Andrew (@rachelandrew) on CodePen.

Stacking follows document order, so the caption appears above the image since it comes later in the source. You can override this with z-index, giving the caption a higher value if it needs to sit earlier in the source order.

Blending Placed and Auto-Placed Items

Mixing line-based placement with auto-placement requires care. Fully auto-placed items place sequentially, each finding the next available empty cell. The default behavior always moves forward, leaving gaps when items do not fit:

See the Pen Grid Lines: auto-placement by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: auto-placement by Rachel Andrew (@rachelandrew) on CodePen.

Setting grid-auto-flow: dense changes this: items that fit into gaps are pulled out of source order to fill them. With dense packing, item 3 may appear before item 2:

See the Pen Grid Lines: auto-placement and dense packing by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: auto-placement and dense packing by Rachel Andrew (@rachelandrew) on CodePen.

Note that dense packing can break keyboard tab order, since visual layout no longer matches the source order users navigate.

Once some items are explicitly placed, auto-placement starts from the first available gap after those placements. If you deliberately leave a row empty at the top, later auto-placed items will move up into it. In this final example, items 1 and 2 are placed, leaving the first row empty, and subsequent items are drawn into that space:

See the Pen Grid Lines: auto-placement mixed with placed items by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: auto-placement mixed with placed items by Rachel Andrew (@rachelandrew) on CodePen.

Keep this in mind: introducing new elements without explicit placement can result in them appearing in unexpected positions relative to your intended design.

Wrapping Up

Grid lines always exist, no matter which higher-level placement technique you use. Even named areas and auto-placement rely on that underlying numbered structure. For any item, you can always position it from one line to another — and now you have the full toolkit for doing so: start and end properties, the grid-area shorthand, named lines, the span keyword, and an understanding of how explicit, implicit, and auto-placed items interact.