Kodokon kodokon.com

Expert grids: subgrid, auto-fit and minmax

Build self-adapting grids without media queries and align nested components on the parent's tracks with subgrid.

10 min · 3 questions

Open this lesson in Kodokon

repeat(auto-fill, ...) and repeat(auto-fit, ...) create as many tracks as the container's width allows. The difference only shows when there are fewer items than possible tracks: auto-fill keeps the empty tracks (your two cards stay at their minimum size, with empty space on the right), whereas auto-fit collapses the empty tracks to zero - the occupied tracks, given a 1fr maximum, then absorb all the freed space and your two cards stretch across the full width.

CSS
.gallery-fill {
  display: grid;
  grid-template-columns: repeat(
    auto-fill, minmax(150px, 1fr)
  );
}
.gallery-fit {
  display: grid;
  grid-template-columns: repeat(
    auto-fit, minmax(150px, 1fr)
  );
}
With 2 items in 900px: fill keeps 6 tracks (2 full, 4 empty), fit collapses the empty ones and stretches the 2 items.

Two minmax() traps even senior developers run into. First: minmax(240px, 1fr) overflows when the container is narrower than 240px - the minimum is a hard floor. The idiomatic fix nests a comparison function: minmax(min(100%, 240px), 1fr). Second: 1fr alone is equivalent to minmax(auto, 1fr); the auto minimum lets unbreakable content (a long URL, a <pre>) widen the track beyond its share. minmax(0, 1fr) locks the distribution.

CSS
.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, 240px), 1fr)
  );
}
The canonical responsive grid with no media query: never overflows, even under 240px wide.

subgrid solves the old problem of alignment across nested components. With grid-template-rows: subgrid, the inner grid does not invent its own tracks: it adopts the parent's over the area it spans. It also inherits the parent's line names (and can add its own), as well as the gap, which it can override locally. The classic case: cards whose title, description and footer align horizontally from one card to the next, whatever the length of their content - impossible to do cleanly before subgrid, because each card computed its heights in isolation.

CSS
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}
.card {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: 0.5rem;
}
Each card spans 3 rows of the parent and adopts them: titles, texts and footers align across cards.

Knowledge check

Make sure you remember the key points of this lesson.

  1. A container can hold 6 tracks but contains only 2 items. What is the difference between auto-fill and auto-fit?
    • None, they are two aliases for the same value
    • auto-fill keeps 4 empty tracks; auto-fit collapses them and the 2 items stretch
    • auto-fit always creates more tracks than auto-fill
  2. What exactly does an element declared with grid-template-rows: subgrid adopt?
    • Only the parent's row count
    • The parent's track sizes and line names over the spanned area, with the gap inherited but overridable
    • All of the parent's grid properties, including its named areas
  3. Why write minmax(min(100%, 240px), 1fr) rather than minmax(240px, 1fr)?
    • To guarantee 240px on every screen
    • To avoid overflow when the container is narrower than 240px
    • Because min() has been mandatory inside repeat() since Grid Level 2