skip to content

When a CSS grid uses `grid-template-columns: subgrid`, what does it inherit from the parent grid besides the track sizes, and what can it still override?

level: middleimportance: should knowfreq 35%

answer

  1. not just track sizes
  2. gutters come down by default
  3. named lines cross one level
  4. you may override, you may append
  5. padding on the subgrid insets the tracks

basics

~20 s

A subgrid inherits the parent's gutters and its line names on the subgridded axis, in addition to the track sizes. It can override the gutters with its own gap and add extra line names of its own, and the other axis stays fully independent.

solid answer

~50 s

On the subgridded axis, the element takes the parent's track sizes, the parent's gutter, and the parent's line names for the lines it spans. Gutter inheritance matters more than people expect: if the outer grid uses `gap: 2rem`, the subgrid's columns are separated by `2rem` too, without you restating it — which is exactly what keeps sibling subgrids aligned. You can still override it by declaring `gap`, `column-gap` or `row-gap` on the subgrid, which is occasionally what you want for a denser inner rhythm, at the cost of the inner tracks no longer being separated by the same gutter as the parent's. Line names come along too, so a grandchild can be placed with `grid-column: content-start / content-end` if the outer grid declared those names. You can append your own names in the value — `grid-template-columns: subgrid [inner-start] [inner-end]` — and the axis you did not subgrid keeps whatever template you gave it.

code

css · 18 lines
css
.page {
  display: grid;
  grid-template-columns:
    [full-start] 1fr
    [content-start] minmax(0, 60rem) [content-end]
    1fr [full-end];
  gap: 1.5rem;
}

.section {
  grid-column: full-start / full-end;
  display: grid;
  grid-template-columns: subgrid [pad-start] [pad-end];
}

.section > figure {
  grid-column: content-start / content-end;
}

go deeper

for a junior

Remember that a subgrid picks up the parent's gutter automatically, so you do not restate gap inside it, and that the axis you did not subgrid behaves like a normal grid.

for a middle

Be able to list what travels down the subgridded axis — track sizes, gutters, line names — and show that gap on the subgrid overrides the inherited gutter.

for a senior

Demonstrate diagnosis: when inner content is a few pixels off the parent's lines, know to check for an overridden gap or padding on the subgrid box before doubting the tracks.

for a principal

Own the naming contract: decide which line names the outer layout publishes for nested components to place against, and treat renaming them as a breaking change to the design system.

## More than track sizes travels down It is easy to read `subgrid` as "copy the parent's track sizes". It is broader than that: on the subgridded axis, the element participates in the parent's grid rather than building one of its own, so several things come along. ## Gutters The gap between tracks is inherited from the parent grid. Given: ```css .outer { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem; } .inner { grid-column: span 4; display: grid; grid-template-columns: subgrid; /* also inherits the 2rem gutter */ } ``` `.inner` has four columns separated by `2rem`, and — critically — those gutters sit at exactly the same positions as the outer grid's. That is what makes the alignment exact rather than approximately right: if the subgrid used its own initial `gap: 0`, its tracks would be wider and its lines would drift away from the parent's. The inheritance is a default, not a lock. Declaring `gap`, `row-gap` or `column-gap` on the subgrid overrides the inherited value for that axis: ```css .inner { grid-column: span 4; display: grid; grid-template-columns: subgrid; column-gap: 0.5rem; /* tighter inner rhythm; track edges shift */ } ``` Use this deliberately. The moment you change the gutter, the inner track *edges* no longer coincide with the parent's lines even though the outer boundary still does, so cross-sibling alignment of anything except the outermost lines is gone. If the reason you reached for subgrid was alignment, leave the gutter inherited. ## Line names Named lines on the parent are visible inside the subgrid for the range it spans, so grandchildren can be placed by name: ```css .page { display: grid; grid-template-columns: [full-start] 1fr [content-start] minmax(0, 60rem) [content-end] 1fr [full-end]; } .section { grid-column: full-start / full-end; display: grid; grid-template-columns: subgrid; } .section > figure { grid-column: content-start / content-end; /* the parent's names, one level down */ } ``` This is the part that makes subgrid feel like a real layout contract rather than a sizing trick: a nested component can address the page's own named regions. You can also add names, by writing a line-name list after the keyword. `grid-template-columns: subgrid [inner-start] [mid] [inner-end]` keeps the inherited tracks and attaches those names, in order, to the subgrid's lines. The names accumulate; the inherited names stay usable. ## What does not change - **The other axis.** Subgridding rows says nothing about columns. `grid-template-rows: subgrid` alongside `grid-template-columns: repeat(2, auto)` is completely normal. - **Alignment properties.** `align-items`, `justify-items` and friends are not inherited from the parent grid by the subgrid — they are ordinary properties you set where you want them. - **Placement of the subgrid itself.** The element still has to be placed in the parent with `grid-column` / `grid-row`; the span is what decides how many tracks it inherits. ## The padding caveat One detail catches people out. The subgrid's tracks are laid out inside its content box, while its grid area is pinned to the parent's lines. Add `padding` or a `border` to the subgrid element and its whole track area is inset, so its lines stop matching the parent's. When exact alignment is the goal, move that padding onto the grandchildren, or onto a wrapper that is not the subgrid itself. ## What to say in an interview Summarise it as: track sizes, gutters and line names on the subgridded axis; gutters overridable, names extendable, the other axis untouched; and watch padding on the subgrid box. That answer shows you have actually built with it rather than read the headline.

  • If a subgrid overrides the inherited gap, what breaks?
    The outer edges of the subgrid still sit on the parent's lines, but every interior track edge shifts, because the space is redistributed with a different gutter. Anything you were aligning to an interior line — across sibling subgrids, or against the parent's own direct children — stops matching. Override the gap only when the inner rhythm matters more than the alignment.
  • Are alignment properties like `align-items` inherited from the parent grid by a subgrid?
    No. Subgridding shares tracks, gutters and line names on that axis; it does not copy the parent's box-alignment properties. `align-items`, `justify-items`, `align-content` and `justify-content` are set on whichever grid container you want them to apply to, exactly as on any other grid.
  • Why does adding padding to a subgrid element break alignment with its parent's lines?
    The element's grid area is fixed to the parent's lines, but its tracks are laid out within its content box. Padding shrinks that content box, so the whole track area is inset and each inherited line lands a little in from where the parent's line is. Put the padding on the grandchildren instead.

saying these in an interview costs you the question

  • Assuming a subgrid starts with gap: 0 and restating the parent's gap
  • Thinking inherited line names are unusable one level down
  • Believing subgrid also copies the parent's align-items
  • Adding padding to the subgrid box and expecting lines to still match
  • Thinking subgrid forces both axes to be inherited

context