How do implicit and explicit grid tracks differ?

Advanced15 min interview
Skills tested:
Distinguishing declared tracks from generated onesKnowing that grid-template-rows sizes only explicit rowsUsing grid-auto-rows and grid-auto-columns to size implicit tracksExplaining how grid-auto-flow decides which axis grows implicitlyKnowing that implicit tracks cannot be named and affect negative line numbers

Advertisement

🧩 Scenario

Almost every real Grid contains implicit tracks, because item counts come from data rather than from the stylesheet. A card gallery declares three columns and lets the rows generate themselves; a dashboard declares two rows and lets a widget placed at row 5 create the ones in between. The distinction matters because grid-template-rows silently does not apply to those generated rows, which is the reason a grid that looks correct for the first two rows collapses for the rest.

Architecture Walkthrough

The Explicit Grid Is What You Declared

The explicit grid consists of exactly the tracks you defined with grid-template-columns, grid-template-rows, and grid-template-areas. Those tracks exist whether or not any item occupies them, and they are the ones whose sizes you controlled directly.

grid-template-columns: repeat(3, 1fr) with grid-template-rows: 200px 200px creates an explicit grid of three columns and two rows: six cells, all sized as declared.

The Implicit Grid Is Everything Else

The implicit grid is made of tracks the browser generates because items need somewhere to go. It is created in two situations.

More items than explicit cells. Nine items in the six-cell grid above means rows three and four must be generated. Grid never errors or clips for lack of space; it grows.

Out-of-range placement. An item with grid-row: 5 in a two-row grid causes rows three, four, and five to be generated, including the empty ones in between. Placement outside the declared grid is a valid instruction to extend it, not a mistake.

Implicit tracks are functionally real: items are laid out in them, gaps apply between them, and alignment works normally. They differ in two ways that matter.

grid-template-rows Does Not Size Them

This is the practical heart of the question. grid-template-rows sizes only the explicit rows. Implicit rows are sized by grid-auto-rows, which defaults to auto, meaning each generated row sizes to its tallest item's content.

That is why a gallery with grid-template-rows: 200px 200px and nine cards shows two crisp 200px rows followed by content-height rows that are all slightly different. Nothing is broken; the declaration simply never applied to those rows. grid-auto-rows: 200px fixes it, and grid-auto-rows: minmax(200px, auto) is often better still, giving a minimum height that can grow for long content.

The column-axis equivalent is grid-auto-columns, which matters when grid-auto-flow: column makes the implicit growth horizontal.

The shorthand grid can set both parts in one declaration, but the explicit form is clearer and is what most stylesheets use.

grid-auto-flow Decides Which Axis Grows

grid-auto-flow controls the auto-placement algorithm and therefore which axis the implicit grid extends along.

row is the default: items fill each row left to right, then wrap to a new implicit row. column fills down each column and then generates new implicit columns instead, which is what you want for a horizontally scrolling row of cards. The dense keyword allows the algorithm to backfill earlier holes with later items that fit, which produces a tighter layout at the cost of putting visual order out of step with DOM order, so it carries the same accessibility caveat as any visual reordering.

Two Limitations of Implicit Tracks

They cannot be named. Line names come from the track list or from grid-template-areas, both of which define the explicit grid only. An implicit track has line numbers but no names, so named-line placement cannot target it.

Negative line numbers count from the end of the explicit grid. grid-column: -1 refers to the last line of the explicit grid, not the last line including implicit tracks. In a grid where implicit columns have been generated, -1 therefore points somewhere in the middle rather than at the visual end, which is a genuinely surprising result and the reason negative indexing is unreliable in grids whose size is data-driven.


Key Code Explained

/* Explicit: 3 columns x 2 rows = 6 declared cells */
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 200px 200px;
  gap: 16px;
}
/* With 9 items, rows 3 and 4 are IMPLICIT.
   grid-template-rows does not size them, so they fall back to auto. */

/* Size the implicit rows too */
.gallery-fixed {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px; /* every generated row is 200px */
  gap: 16px;
}

/* Usually better: a floor that can still grow for long content */
.gallery-flexible {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(200px, auto);
  gap: 16px;
}

/* Out-of-range placement GENERATES tracks rather than erroring */
.dashboard {
  display: grid;
  grid-template-rows: auto auto; /* 2 explicit rows */
}
.dashboard .late-widget {
  grid-row: 5; /* rows 3, 4, and 5 are generated, 3 and 4 stay empty */
}

/* grid-auto-flow: column makes the implicit growth HORIZONTAL */
.carousel {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(240px, 1fr); /* sizes the implicit COLUMNS */
  gap: 16px;
  overflow-x: auto;
}

/* dense backfills holes — tighter layout, DOM order diverges from visual */
.masonry-ish {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-flow: row dense;
}

/* Named lines exist only on the EXPLICIT grid */
.named {
  display: grid;
  grid-template-columns: [start] 1fr [mid] 1fr [end];
}
/* An implicit third column has numbers but no names — [end] cannot reach it */

/* Negative line numbers count from the EXPLICIT end */
.trap {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* explicit lines 1..4 */
}
.trap .stretch {
  grid-column: 1 / -1; /* spans the 3 explicit columns.
     If implicit columns were generated, -1 is still explicit line 4,
     so this does NOT reach the visual end of the grid. */
}

The .gallery and .gallery-fixed pair is the example that explains the most real bug reports. The first two rows honour the 200px declaration and every row after them does not, which reads as the browser ignoring the property intermittently. Once you know grid-template-rows addresses only declared rows, the fix is obvious and the behaviour stops being mysterious.

The .trap block is the subtler point. grid-column: 1 / -1 is the standard idiom for "span the full width," and it is correct as long as no implicit columns exist. In a grid using grid-auto-flow: column, or one where out-of-range placement generated columns, -1 still resolves to the last explicit line and the span falls short of the visual edge.


Tradeoffs

AspectExplicit tracksImplicit tracks
Created bygrid-template-columns / -rows / -areasAuto-placement or out-of-range placement
Sized byThe template declarationgrid-auto-rows / grid-auto-columns, default auto
Can be namedYesNo
Reachable by negative line numbersYes, -1 is the explicit endNot by negative numbers
Exists with no itemsYesNo
Growth axisDeclaredControlled by grid-auto-flow

What Interviewers Actually Check

  • Whether you can define both terms precisely rather than approximately
  • Whether you know grid-template-rows does not size implicit rows
  • Whether you reach for grid-auto-rows and know its default is auto
  • Whether you know out-of-range placement generates tracks rather than failing
  • Whether you know negative line numbers count from the explicit end

Follow-Up Questions

  1. Why does grid-auto-rows: minmax(200px, auto) usually beat a fixed grid-auto-rows: 200px in a content-driven gallery?
  2. What accessibility problem does grid-auto-flow: dense introduce, and how would you decide whether it is acceptable?
  3. How does the grid shorthand express both explicit and implicit track sizing, and why is it rarely used?
  4. If an item is placed at grid-row: -5 in a grid with two explicit rows, what happens?
  5. How does subgrid interact with the implicit grid of the parent?

Common Candidate Mistakes

  • Expecting grid-template-rows to size rows that were never declared, then concluding the property is applied inconsistently when only the first few rows honour it
  • Not knowing implicit tracks default to auto sizing, which produces rows of slightly different heights in a gallery that was meant to be uniform
  • Treating out-of-range placement such as grid-row: 5 in a two-row grid as an error, when it validly generates the intervening tracks including empty ones
  • Using grid-column: 1 / -1 in a grid that has generated implicit columns, where -1 resolves to the last explicit line and the span stops short of the visual edge
  • Forgetting that grid-auto-flow: column moves implicit growth to the horizontal axis, so grid-auto-rows no longer applies and grid-auto-columns is the relevant property

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you define explicit and implicit tracks precisely?
  • Can you explain why grid-template-rows appears to be ignored for later rows?
  • Can you size implicit tracks correctly on both axes?
  • Can you explain how grid-auto-flow changes which axis grows implicitly?
  • Can you explain what negative line numbers count from and when that becomes a trap?

Summary

The explicit grid is exactly what you declared with grid-template-columns, grid-template-rows, and grid-template-areas. Those tracks exist regardless of content and are sized by those declarations. The implicit grid consists of tracks the browser generates when there are more items than declared cells, or when an item is placed outside the declared range, which extends the grid rather than producing an error.

The distinction has one consequence that causes most of the confusion: grid-template-rows sizes only explicit rows. Implicit rows are sized by grid-auto-rows, which defaults to auto, so a gallery with two declared 200px rows and nine cards shows two uniform rows followed by content-height ones. grid-auto-rows: minmax(200px, auto) is usually the right fix, giving a floor that can still grow. grid-auto-columns is the horizontal equivalent, and it becomes the relevant property when grid-auto-flow: column moves implicit growth to the inline axis.

Two limitations distinguish implicit tracks beyond sizing. They cannot carry line names, since names come only from the explicit track list or template areas. And negative line numbers count from the end of the explicit grid, so the common grid-column: 1 / -1 full-width idiom stops short of the visual edge in any grid where implicit columns have been generated.

Frequently Asked Questions

Why do my grid rows ignore grid-template-rows after the first few?

Because those rows are implicit. grid-template-rows only sizes the explicit rows you declared; everything beyond them is sized by grid-auto-rows, which defaults to auto.

Can you name implicit tracks?

No. Implicit tracks cannot carry line names, and negative line numbers count from the end of the explicit grid, which is why negative indexing behaves unexpectedly when implicit rows exist.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement