Skip to main content

๐Ÿ“ Grid Item Placement and Alignment

The container sets the stage; the items take their marks. This lesson is all about the child side of Grid โ€” pinning items to exact lines, spanning tracks, aligning each item inside its cell, reordering visually, and even layering items on top of one another.

๐ŸŽฏ Learning Objectives

By the end of this lesson, you will be able to:

  • Place items by line number, negative line, named line, and the span keyword
  • Use grid-area both to assign named areas and as the four-value placement shorthand
  • Combine auto-placement with explicit placement in one grid
  • Align individual items with justify-self, align-self, and place-self
  • Reorder items visually with order and stack overlapping items with z-index โ€” and know the accessibility caveats

Estimated Time: 40โ€“50 minutes  โ€ข  Difficulty: Intermediate

Hands-on: Build a magazine-style article layout with a spanning hero, a pull-quote, and a sidebar.

In This Lesson

Lines, Areas & Numbering

Every item you place references grid lines โ€” the numbered dividers between tracks. Numbering starts at 1 on the left/top and, crucially, also runs backwards from the end: -1 is the last line, -2 the second-to-last, and so on. That backward numbering is your best friend when the track count is dynamic.

Grid line numbering, positive and negative A four-column, two-row grid whose column lines are numbered 1 to 5 from the left and -5 to -1 from the right. 1 2 3 4 5 -5 -4 -3 -2 -1
Figure 1 โ€” Column lines counted from the left (blue, positive) and from the right (amber, negative). grid-column: 1 / -1 always spans the full width, however many columns exist.

A grid area is any rectangle bounded by four lines: a single cell, a run of cells, or a region named through grid-template-areas. Think of areas as rooms โ€” each has defined walls, and some are bigger than others.

Line-Based Placement

Four long-hand properties pin an item to specific lines; two shorthands express the same thing more compactly.

/* Long-hand */
.item {
  grid-row-start: 1;
  grid-row-end: 3;      /* occupies rows between line 1 and line 3 */
  grid-column-start: 2;
  grid-column-end: 4;
}

/* Shorthand: start / end */
.item {
  grid-row: 1 / 3;
  grid-column: 2 / 4;
}

Negative lines for end-anchored items

Because -1 is always the final line, negative numbers let you anchor to the end without knowing the track count:

/* Full-width banner, no matter how many columns */
.banner { grid-column: 1 / -1; }

/* Bottom-right cell of any grid */
.badge {
  grid-row: -2 / -1;
  grid-column: -2 / -1;
}

Named lines

If the container named its lines (or you used grid-template-areas, which creates *-start/*-end names for free), place items with words:

.header  { grid-column: sidebar-start / content-end; }
.sidebar { grid-row: main-start / footer-end; }

The span Keyword

Often you care how many tracks an item covers, not exactly where it ends. The span keyword says "start here, then cover N tracks":

.feature {
  grid-column: 1 / span 3;   /* start at line 1, cover 3 columns */
  grid-row: 2 / span 2;      /* start at line 2, cover 2 rows */
}

/* Span backwards from the end */
.tail { grid-column: span 2 / -1; }  /* cover 2 columns, ending at the last line */

It's like asking a restaurant for "a table for four" instead of "table number 12" โ€” you state the size, not the exact spot. This keeps layouts resilient when the surrounding track count changes.

๐Ÿ’ก Shorthand for a single edge

Writing just grid-column: span 2 (no start line) lets the auto-placement algorithm choose the starting line, then reserves two columns from there โ€” handy inside auto-flowed galleries.

The grid-area Shorthand

grid-area wears two hats.

1) Assign a named area

.container {
  display: grid;
  grid-template-areas:
    "header  header  header"
    "sidebar content content"
    "footer  footer  footer";
}
.header  { grid-area: header; }
.content { grid-area: content; }

2) Place with four lines at once

As a pure placement shorthand, grid-area takes four values in a clockwise-ish order that trips everyone up at first:

/* grid-area: row-start / column-start / row-end / column-end */
.item { grid-area: 1 / 2 / 3 / 4; }
The four-value order of grid-area A square showing the grid-area value order: row-start at top, column-start at right, row-end at bottom, column-end at left. 1 ยท row-start 2 col-start 3 ยท row-end 4 col-end
Figure 2 โ€” Read grid-area as top โ†’ right โ†’ bottom โ†’ left: row-start, column-start, row-end, column-end.

The four-value form is compact but hard to read; for anything complex, named areas or separate grid-row/grid-column declarations are kinder to the next developer.

Auto vs. Explicit Placement

You can mix both strategies in a single grid: pin the important items, and let the rest flow.

.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px;
  gap: 20px;
}

/* One explicitly placed hero */
.featured {
  grid-column: 1 / 3;   /* first two columns */
  grid-row: 1 / 3;      /* first two rows */
}

/* Everything else auto-places around it */
.gallery-item { /* no placement โ€” flows automatically */ }

It's like a restaurant with one reserved table (explicit) while other diners are seated wherever there's room (auto). The auto-placement algorithm โ€” steered by the container's grid-auto-flow โ€” fills the remaining cells, flowing around your pinned hero.

Per-Item Alignment

The container's justify-items/align-items set defaults for all items. Any single item can override them with the -self variants. By default items stretch to fill their cell.

PropertyAxisValues
justify-selfinline (โ†’)start ยท center ยท end ยท stretch
align-selfblock (โ†“)start ยท center ยท end ยท stretch
place-selfbothalign-self justify-self
.item {
  justify-self: end;      /* push to the right of its cell */
  align-self: center;     /* center vertically in its cell */
  place-self: center end; /* shorthand: align-self=center, justify-self=end */
}
justify-self values inside a cell Four identical cells showing an item positioned start, center, end, and stretched across the cell. start center end stretch (default)
Figure 3 โ€” justify-self positions an item along the row axis inside its cell. align-self does the same vertically.

order & z-index

Reordering with order

Every grid item has order: 0 by default and paints in source order. Change the number to move an item visually without touching the HTML โ€” lower orders come first, and equal orders keep source order.

.promo   { order: -1; }  /* jump to the front */
.legal   { order: 1; }   /* drift to the back */

โš ๏ธ Accessibility caveat

order only changes the visual order. Keyboard tab order and screen-reader reading order still follow the DOM. A large gap between the two disorients keyboard and assistive-tech users. Use order for small tweaks, keep the source order sensible, and always test with the keyboard.

Layering with z-index

Items placed in overlapping cells stack. Unlike positioned elements, grid items obey z-index without needing position: relative:

.card { display: grid; grid-template: repeat(12, 1fr) / repeat(12, 1fr); }

.card-image   { grid-area: 1 / 1 / 13 / 13; z-index: 1; }
.card-overlay { grid-area: 8 / 1 / 13 / 13; z-index: 2; }
.card-text    { grid-area: 9 / 2 / 12 / 12; z-index: 3; color: #fff; }

Here an image fills the whole card, a gradient overlay covers its lower third, and the text sits on top โ€” three items sharing cells, layered by z-index. Perfect for hero cards, badges, and captions.

Hands-on Exercise

๐Ÿ‹๏ธ Magazine-Style Article Layout

Objective: Use a 12-column grid to compose an article with a full-width headline and hero image, a narrower reading column, a pull-quote, and a sidebar โ€” then collapse it to one column on mobile.

Requirements

  1. A 12-column grid with a comfortable gap.
  2. Headline and hero image span the full width (1 / -1).
  3. Body text sits in a centered reading column (roughly columns 3โ€“11).
  4. A pull-quote spans a few left columns; a sidebar occupies the right, spanning two rows.
  5. Below 768px, every element collapses to a single column.
๐Ÿ’ก Hint

Set grid-template-columns: repeat(12, 1fr) and place each element with grid-column. Give the sidebar grid-row: span 2 and align-self: start so it doesn't stretch. In the mobile media query, set every element to grid-column: 1 / -1.

โœ… Solution
.article {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: minmax(min-content, auto);
  gap: 20px;
  padding: 30px;
}

.article-header { grid-column: 1 / -1; text-align: center; }
.article-image  { grid-column: 1 / -1; }
.article-lead   { grid-column: 3 / 11; font-size: 1.2em; }
.article-body   { grid-column: 3 / 11; line-height: 1.6; }

.article-quote {
  grid-column: 2 / 6;
  align-self: center;
  font-size: 1.4em;
  font-style: italic;
  border-left: 4px solid currentColor;
  padding-left: 1rem;
}

.article-sidebar {
  grid-column: 8 / 12;
  grid-row: span 2;
  align-self: start;
  padding: 1rem;
  border: 1px solid #ddd;
  border-radius: 8px;
}

@media (max-width: 768px) {
  .article { grid-template-columns: 1fr; }
  .article > * { grid-column: 1; }
}

On desktop you get a rich, asymmetric editorial layout; below 768px it gracefully stacks into one readable column โ€” same HTML throughout.

Best Practices

โœ… Do

  • Prefer grid-column: 1 / -1 for full-width items so they survive column-count changes.
  • Use named lines/areas for complex placement; line numbers for simple spans.
  • Reach for span when you care about size, not the exact end line.
  • Let overlapping grid items layer with z-index โ€” no position hack required.

โš ๏ธ Don't

  • Don't overuse order โ€” it divorces visual order from DOM order and hurts accessibility.
  • Don't forget the grid-area value order is row-start / column-start / row-end / column-end.
  • Don't create accidental overlaps; double-check that placements don't collide unless you mean them to.

Summary & Quiz

๐ŸŽ‰ Key Takeaways

  • Place items by line number, negative line (-1 = last), named line, or span.
  • grid-area assigns a named area or sets four lines: row-start / column-start / row-end / column-end.
  • Explicit and auto placement coexist โ€” pin the heroes, flow the rest.
  • justify-self/align-self/place-self override container alignment for a single item.
  • order reorders visually only (mind accessibility); overlapping items stack with z-index, no position needed.

๐ŸŽฏ Quick Quiz

Question 1: Which declaration makes an item span the full width of a grid no matter how many columns it has?

Question 2: In grid-area: 1 / 2 / 3 / 4, what does the value 2 represent?

Question 3: What is the key accessibility concern with the order property?

๐Ÿ“š Further Reading

๐Ÿš€ What's Next?

You've now completed the full CSS Grid toolkit โ€” container and items alike. Next we step back to the bigger picture with Responsive Design Philosophy, where these layout tools serve a mobile-first, content-driven strategy.

๐ŸŽ‰ Grid complete!

Container plus items means you can build essentially any modern layout. Time to zoom out and think about responsiveness as a whole.