How do implicit and explicit grid tracks differ?
Advertisement
🧩 Scenario
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
| Aspect | Explicit tracks | Implicit tracks |
|---|---|---|
| Created by | grid-template-columns / -rows / -areas | Auto-placement or out-of-range placement |
| Sized by | The template declaration | grid-auto-rows / grid-auto-columns, default auto |
| Can be named | Yes | No |
| Reachable by negative line numbers | Yes, -1 is the explicit end | Not by negative numbers |
| Exists with no items | Yes | No |
| Growth axis | Declared | Controlled by grid-auto-flow |
What Interviewers Actually Check
- Whether you can define both terms precisely rather than approximately
- Whether you know
grid-template-rowsdoes not size implicit rows - Whether you reach for
grid-auto-rowsand know its default isauto - 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
- Why does
grid-auto-rows: minmax(200px, auto)usually beat a fixedgrid-auto-rows: 200pxin a content-driven gallery? - What accessibility problem does
grid-auto-flow: denseintroduce, and how would you decide whether it is acceptable? - How does the
gridshorthand express both explicit and implicit track sizing, and why is it rarely used? - If an item is placed at
grid-row: -5in a grid with two explicit rows, what happens? - How does subgrid interact with the implicit grid of the parent?
Common Candidate Mistakes
- Expecting
grid-template-rowsto 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
autosizing, 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: 5in a two-row grid as an error, when it validly generates the intervening tracks including empty ones - Using
grid-column: 1 / -1in a grid that has generated implicit columns, where-1resolves to the last explicit line and the span stops short of the visual edge - Forgetting that
grid-auto-flow: columnmoves implicit growth to the horizontal axis, sogrid-auto-rowsno longer applies andgrid-auto-columnsis 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-rowsappears to be ignored for later rows? - Can you size implicit tracks correctly on both axes?
- Can you explain how
grid-auto-flowchanges 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.
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