Why the last row stretches, and how to stop it
CaveatThe two keywords are identical until the items run out, which is why the difference never shows up in the design and always shows up in production: auto-fit collapses the empty tracks, so three cards in a six-track row grow to a third of the width each, and auto-fill keeps them, so three cards stay card-sized and the rest of the row is blank. Neither is the right answer on its own. Separately, 1fr is minmax(auto, 1fr) and that auto floors at min-content, so one long URL or a <pre> pushes its track past its share and the whole grid overflows sideways — minmax(0, 1fr) is the fix and costs nothing.
FallbackAn engine with no grid falls back to block flow: every item full width, stacked, which is the small-screen layout anyway. That is why this pattern never needed a float ladder underneath it. What it does need is a sane minimum — set the minmax() floor below your narrowest real card, or the tracks stop shrinking and the container scrolls instead of reflowing.
.grid {
/* fit collapses empty tracks and
stretches what is left. fill
keeps them and holds the size */
grid-template-columns:
repeat(auto-fill, minmax(60px, 1fr));
}
.grid li {
/* 1fr floors at min-content: one
long word overflows the row */
grid-column: span 1;
min-width: 0;
}
Published
Questions
Why do three cards stretch across the whole row?
auto-fit collapses the tracks that have no item in them and hands their space to the ones that do. Use auto-fill if the cards should keep their size and leave the rest of the row empty.
Why does my grid overflow sideways?
1fr is minmax(auto, 1fr), and that auto never shrinks below the content's minimum width. One long URL, a wide table or a <pre> pushes its track past its share. Write minmax(0, 1fr).
Which of auto-fit and auto-fill is the safe default?
Neither, but auto-fill surprises people less: it behaves the same whether the list is full or nearly empty. Reach for auto-fit only when a short list genuinely should fill the width.