AniUI Academy

CSS Grid Fundamentals

display grid, grid-template-columns/rows with the fr unit, gap, naming regions with grid-template-areas/grid-area, and placing items by line number with grid-column/grid-row.

9 min read

Flexbox arranges items along one axis at a time. Grid is different: it lets you define rows and columns together, as one coordinated structure, and place items anywhere within it — by track size, by name, or by line number. This is the tool for laying out a whole page section, not just a single row.

Turning on grid

.container {
  display: grid;
}

Just like display: flex, this changes how direct children of .container behave — but instead of lining up along one axis, they now flow into cells of a grid you define with grid-template-columns and grid-template-rows.

Explicit tracks and the fr unit

.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;
  grid-template-rows: 100px auto;
}

grid-template-columns lists a size for each column track, left to right. Here there are three columns: a fixed 200px, then two equal 1fr tracks.

fr stands for a fraction of the remaining space — space left over after every fixed-size track has already been subtracted. In the example above, whatever width remains after the fixed 200px column is split evenly between the two 1fr columns, because they both claim one fraction each. Change one to 2fr and it claims twice as much of that remaining space as the 1fr beside it — the exact same idea as flex-grow from flexbox, just applied to a whole track instead of one flex item.

grid-template-rows works identically, but for row heights. auto sizes a row to fit its content naturally.

gap

.container {
  display: grid;
  gap: 1.5rem;          /* both row-gap and column-gap */
  gap: 1rem 2rem;        /* row-gap: 1rem; column-gap: 2rem; */
}

gap inserts consistent spacing between grid tracks, in both directions at once (or independently, if you pass two values) — the same idea as flexbox's gap, just applied to a two-dimensional grid instead of a single row.

Naming regions with grid-template-areas

For a layout with a fixed shape — a header, a sidebar, a main content area, a footer — naming each region directly is often clearer than reasoning about raw line numbers.

.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}
 
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

Each quoted string in grid-template-areas is one row of the grid, and each word inside it is a column in that row. Repeating a name across cells (like header appearing twice) makes that single region span both of those columns. Every child is then placed simply by naming which area it belongs to with grid-area — no line numbers, no counting columns, just a name that matches the ASCII-art layout above it.

Placing items explicitly by line number

Grid lines are numbered, starting at 1, running along both the column and row directions. You can place an item directly onto specific lines instead of naming a region:

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
 
.wide-item {
  grid-column: 1 / 3;  /* spans from column line 1 to column line 3 — two tracks wide */
}
.tall-item {
  grid-row: 1 / 3;      /* spans from row line 1 to row line 3 — two tracks tall */
}

grid-column: 1 / 3 doesn't mean "3 columns wide" — it means "span from line 1 to line 3," which covers exactly two column tracks between those two lines. This is the most precise way to place an item, useful when a layout doesn't map cleanly onto a named-region shape, or when you want one item to deliberately span multiple tracks.

repeat(4, 1fr) above is shorthand for writing 1fr 1fr 1fr 1fr — a quick way to define several equal tracks without repeating yourself.

Try it yourself

A three-column grid mixes a fixed track with two fr tracks, then a second grid uses named areas for a header/sidebar/main/footer shape — the exact pattern the next lesson builds into a full real page layout.

Try it yourself
Loading playground...

What to remember

  • display: grid lays out direct children into rows and columns you define together, not one axis at a time.
  • grid-template-columns/grid-template-rows set explicit track sizes; fr distributes leftover space after fixed tracks are subtracted.
  • gap (or row-gap/column-gap) spaces tracks apart, the same idea as flexbox's gap.
  • grid-template-areas names rectangular regions in ASCII-art form; children are placed into them with grid-area.
  • grid-column/grid-row place items explicitly by line number — 1 / 3 spans from line 1 to line 3, covering two tracks.

Check yourself

4 questions · pass 3/4 to unlock CSS Grid in Practice

up to 50
  1. 1.In grid-template-columns: 200px 1fr 1fr;, what does the second column get?

  2. 2.What does grid-template-areas let you do?

  3. 3.What does grid-column: 1 / 3; do to an item?

  4. 4.What is the gap property shorthand for?

4 left to answer