Tools · CSS · Grid-Spielwiese · Anleitungen · Why CSS Grid Draws the Layout Before the Content Arrives
Why CSS Grid Draws the Layout Before the Content Arrives
Most layout in CSS grows outward from the content. A paragraph is as tall as its text, an inline row is as wide as its children, and the container follows along. CSS Grid works the other way. The container declares its columns and rows before a single item is placed, and the items are then dropped onto that structure. That one change is why grid can keep a sidebar, a header and a footer lined up on both axes at once, and also why its vocabulary of tracks, lines and fractions takes a moment to click.
Tracks first, items second
grid-template-columns: repeat(3, 1fr) says three column tracks exist before anything is inside them. The tracks have sizes, and the space between them is the gap. Each item then lands in a cell, either where the browser's auto-placement puts it, the next free cell in reading order, or where you send it with grid-column and grid-row.
The grid playground's own tool page is a working example. Its how-it-works steps sit in a grid with repeat(3, 1fr) and a 16px gap, and below 820px the same rule switches to a single 1fr column. The three list items have no layout code of their own. The parent changed its mind, and they moved.
Lines, not cells
Placement in grid is described in lines. Three columns have four column lines: one before the first track, one between each pair, and one after the last. grid-column: 1 / 3 means "from line 1 to line 3", which covers two tracks. grid-column: 1 / span 2 means the same thing, said as a start and a count, and it stays right if you later change only the span.
Two details save a lot of counting. Negative numbers count from the end, so 1 / -1 always means "the full width of the explicit grid", whatever the column count. And line 1 is at the start of the writing direction, not the left edge: on a right-to-left page the same CSS puts column 1 on the right, with no extra code.
What 1fr really shares
The fr unit is a share of the space that is left once fixed-size tracks and gaps are taken out. In a 600px container with two 20px gaps and three 1fr columns, 560px is shared three ways. Make one column 2fr and it gets half of the 560px, the other two a quarter each.
One catch matters in real pages. A bare 1fr is really minmax(auto, 1fr): the track will not shrink below the widest unbreakable thing inside it. One long URL in a card can push its whole column wider than its share and stretch the grid past the container. Writing minmax(0, 1fr) gives the track permission to be smaller than its content, and the content can wrap or scroll inside it.
Grid playground makes the track structure visible: set the column and row counts and the gaps, and it draws the real grid with numbered rails, so you can see which line an item starts on before you write it down. This guide covers placing an item across several tracks, and this one builds a full page layout and fixes what the first version gets wrong.