skip to content

A CSS Grid has grid-template-columns: 1fr 1fr, and one auto-placed item declares grid-column: span 3. What does the browser do?

level: middleimportance: nice to knowfreq 34%

answer

  1. the span wins, not the template
  2. the grid gets wider
  3. explicit tracks vs generated tracks
  4. grid-auto-columns sizes the newcomer
  5. overflow makes rows; spans can make columns

basics

~20 s

The grid widens: before placing anything, auto-placement expands the implicit grid to fit the largest column span among auto-placed items, so a third column is created and the item spans all three. The span is never clamped to the two explicit columns.

solid answer

~40 s

Auto-placement determines how many columns the implicit grid has before it places anything, and part of that step is accommodating spans: if the largest column span among the items without a definite column position is wider than the grid, columns are added to the end to fit it. So `grid-column: span 3` in a two-column template gives you a third column and an item that spans all three. The added column is implicit, not explicit, so it is sized by `grid-auto-columns` — `auto` by default — rather than picking up the `1fr` of the template. That is worth knowing because in row flow this is one of the few ways extra *columns* appear at all; ordinary overflow only ever generates extra rows.

code

html · 14 lines
html
<style>
  .grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }
  .grid > div { background: #cde; padding: 1rem; }
  .wide { grid-column: span 3; }
</style>
<div class="grid">
  <div>one</div>
  <div>two</div>
  <div class="wide">spans three</div>
</div>

go deeper

for a junior

Know the headline outcome: asking for more columns than the template declares makes the grid wider rather than shrinking or clipping the item.

for a middle

Explain that auto-placement fixes the implicit grid's width up front, accommodating the largest span among auto-placed items, and that the generated track is implicit so grid-auto-columns sizes it.

for a senior

Diagnose it in the wild: a mystery extra track usually means a span left over from a wider breakpoint. Keep spans and track counts changing together so the layout stays predictable across viewports.

for a principal

Treat span values as part of the layout contract a design system publishes. Decide whether spans are expressed as tokens tied to the breakpoint's track count, so an item can never ask for more columns than the grid at that size offers.

## The implicit grid is sized before placement runs It is tempting to think of auto-placement as a single walk that grows the grid as it goes. It is not: the algorithm first fixes how wide the grid is (in row flow), then walks. One of the inputs to that width decision is the **largest column span among items that have no definite column position**. If that span is larger than the number of columns the grid otherwise has, columns are appended to the end of the implicit grid until the span fits. ```css .grid { display: grid; grid-template-columns: 1fr 1fr; } .wide { grid-column: span 3; } ``` Two explicit columns, a request for three, so the implicit grid ends up three columns wide. Every item in the container now lays out against a three-column grid, not just the wide one. ## Explicit vs implicit is not cosmetic here The two columns you wrote are **explicit** tracks with the size you gave them (`1fr` each). The third is an **implicit** track, and implicit column tracks take their size from `grid-auto-columns`, whose initial value is `auto`. So the layout is not three equal columns: the third sizes itself to its content, and the two `1fr` tracks divide whatever free space is left after it. Developers who expect `repeat(3, 1fr)` behaviour are surprised by the ragged result, and the fix is either to widen the template or to set `grid-auto-columns` deliberately. ```css .grid { display: grid; grid-template-columns: 1fr 1fr; grid-auto-columns: 1fr; /* now the generated column matches */ } ``` ## Why this is asymmetric with rows In the default `grid-auto-flow: row`, the column count is a **fixed frame** and the row count is **open-ended**: items that run out of room generate new rows indefinitely, but nothing generates a new column merely by overflowing — the cursor wraps instead. A span wider than the frame is the exception, because there is no way to satisfy it by wrapping. Switch to `grid-auto-flow: column` and the roles swap: the row count becomes the fixed frame, and an oversized `grid-row: span n` widens it the same way. ## What this is not - **It is not clamping.** Browsers do not quietly reduce `span 3` to `span 2` to make it fit. - **It is not overflow.** The item does not spill past the container's content box; the grid genuinely has an extra track. - **It does not shrink the item's content.** Track sizing runs after placement, on the grid that placement decided on. One related detail worth keeping straight: this expansion happens for spans, which are *relative*. Placement that names an explicit line is a different mechanism with different behaviour, so do not generalise from one to the other. ## Reading the layout back When a grid mysteriously has one more column than you wrote, the diagnostic path is short: look for an item whose `grid-column` contains a `span` larger than your track count. This often happens accidentally — a `span 3` written for a three-column desktop layout, still applied inside a media query where the template dropped to two columns. The visible symptom is a narrow ragged extra column that no rule seems to define. Making spans responsive alongside the template (`grid-column: auto` or a smaller span at narrow widths) is the usual fix. ## What to say in an interview State the outcome first — the grid gains a column, the span is honoured — then the nuance that the new column is implicit and therefore sized by `grid-auto-columns` rather than by the template. Adding the row/column asymmetry (overflow makes rows, oversized spans make columns) shows you understand the frame-versus-flow shape of the algorithm rather than a memorised fact.

  • Does the generated third column get the 1fr sizing from the template?
    No. The template only sizes the explicit tracks. A track created beyond it is implicit and takes its size from `grid-auto-columns`, whose initial value is `auto`, so it sizes to its content while the two `1fr` tracks share what is left. Setting `grid-auto-columns: 1fr` is how you make the generated column match.
  • Would an oversized span create extra tracks in grid-auto-flow: column as well?
    Yes, with the axes swapped. In column flow the row count is the fixed frame that items wrap within, and the column count grows as items overflow. An auto-placed item declaring `grid-row: span n` larger than the number of rows forces rows to be added so the span can be satisfied, exactly as an oversized `grid-column: span n` adds columns in row flow.
  • How would you spot this in a layout you did not write?
    Look for a grid with one more track than the template declares, usually a narrow ragged one, and search the item rules for a `span` value larger than the track count. It most often appears at a breakpoint where the template shrank but the item's span did not, so making the span responsive alongside the template is the fix.

saying these in an interview costs you the question

  • Thinks the span is clamped to the number of declared columns
  • Expects the generated column to inherit the template's 1fr
  • Says the item overflows the grid container instead
  • Believes row flow can never produce extra columns
  • Assumes the browser shrinks the item's content to fit

context