skip to content

A CSS Grid with grid-template-columns: 1fr 1fr holds a long unbreakable string in one cell, and that column grows past its half, overflowing the container. Why does 1fr not keep the columns equal, and how do you fix it?

level: seniorimportance: must knowfreq 58%

answer

  1. fr is the maximum only
  2. what is the implied minimum?
  3. auto means the content's minimum here
  4. minmax(0, 1fr) or min-width: 0
  5. overflow other than visible zeroes it too

basics

~20 s

A bare 1fr is shorthand for minmax(auto, 1fr), and that auto minimum resolves to the content's minimum size, so a track cannot shrink below the longest unbreakable word. Fix it with minmax(0, 1fr) on the track, or min-width: 0 (or an overflow value other than visible) on the item.

solid answer

~50 s

The `fr` value is only the track's **maximum**. Written out, `1fr` is `minmax(auto, 1fr)`, and in a grid item whose `overflow` is `visible`, that `auto` minimum resolves to the automatic minimum size — effectively the item's min-content contribution, which for text is the longest unbreakable run of characters and for a table or a wide image is its own intrinsic minimum. Track sizing honours minimums before it distributes free space, so the column widens to fit that word and the grid overflows instead of splitting evenly. There are three standard fixes: change the track to `minmax(0, 1fr)` so the floor is explicitly zero; set `min-width: 0` on the grid item, which does the same thing from the item's side; or give the item `overflow: hidden` or `auto`, which changes the automatic minimum size to zero as a side effect. If the content should wrap rather than be clipped, pair the fix with `overflow-wrap: anywhere` so the long token breaks.

code

css · 10 lines
css
.grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
}

.grid > * {
  min-width: 0;
  overflow-wrap: anywhere;
}

go deeper

for a junior

Remember the symptom and the one-line fix: a 1fr column that refuses to shrink usually needs minmax(0, 1fr) or min-width: 0 on the item. Being able to name the fix is enough at this level.

for a middle

Explain the mechanism: 1fr is minmax(auto, 1fr), the auto minimum resolves to the item's content-driven minimum, and track sizing satisfies minimums before distributing free space. Name all three fixes and what each one changes.

for a senior

Diagnose it from computed track sizes rather than guessing, and choose the fix by intent — track-level minmax(0, 1fr) for layout you own, min-width: 0 for a single misbehaving item, overflow only when clipping is actually wanted. Connect it to the classic ellipsis-not-working report.

for a principal

Own the default: deciding whether the base layout primitives ship with zero-floor tracks, and what the house rule is for long unbreakable content — wrap, clip, or scroll — prevents this bug recurring in every new component instead of being patched case by case.

## The bug, precisely ```css .grid { display: grid; grid-template-columns: 1fr 1fr; } ``` Put `supercalifragilisticexpialidocious-and-then-some` in the first cell and the first column stops being half the width. Nothing in the CSS mentions content sizing, so the behaviour looks like a browser bug. It is not. ## fr is a maximum, not a size The track sizing algorithm resolves flexible tracks *last*. Before it distributes any free space, it sizes every track's **base size** from its minimum, and only then grows tracks toward their maximum with whatever space is left. A bare `1fr` expands to: ```css grid-template-columns: minmax(auto, 1fr) minmax(auto, 1fr); ``` The minimum is `auto`, not `0`. So step one already gives the offending column a base size equal to what its content demands, and there is no mechanism later that takes it away — flexible sizing can grow a track above its base size but never below it. ## What `auto` as a minimum actually means For a grid item whose `overflow` is `visible`, an `auto` minimum resolves to the **automatic minimum size**, which is essentially the item's min-content contribution. Concretely: - A paragraph's min-content width is its longest unbreakable run — a long word, a URL, a hash, a filename with no hyphens. - A replaced element such as an `img` contributes its own intrinsic minimum unless constrained. - A nested element with its own content-driven minimum passes that minimum up the chain, so the culprit is often two or three levels deep. That last point is why the same bug in a real app is so hard to see: the wide thing is a `pre` block or an overflowing table inside a card inside the grid item. ## The three fixes ```css /* 1. Explicit zero floor on the track */ .grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } /* 2. Zero floor from the item's side */ .grid > * { min-width: 0; } /* 3. A non-visible overflow makes the automatic minimum zero */ .cell { overflow: hidden; } ``` They are not interchangeable in intent: - `minmax(0, 1fr)` is the most declarative — the track list itself says "these columns are exactly equal, whatever is inside them". It is the right default for layout grids you control. - `min-width: 0` is the right tool when only some items misbehave, or when the grid's track list is generated elsewhere. Its logical equivalent is `min-inline-size: 0` if you are writing writing-mode-agnostic CSS. - `overflow: hidden` (or `auto`, or `clip`) fixes the sizing as a side effect of establishing a scroll container. Reach for it when you *want* the clipping or the scrollbar, not merely as a sizing hack, because it also silently clips shadows, focus rings and popovers that used to escape the box. Removing the floor makes the track equal, but the content still has to go somewhere. Usually you pair the fix with a content rule: ```css .cell { min-width: 0; overflow-wrap: anywhere; /* let the long token break */ } .truncated { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; /* ellipsis needs all three, plus the zero floor */ } ``` The ellipsis case is worth memorising: `text-overflow: ellipsis` inside a grid or flex layout is famous for "not working", and the missing ingredient is almost always the automatic minimum size keeping the box wide enough that there is nothing to truncate. ## The same rule elsewhere The automatic minimum size is not a grid-only concept — the same content floor is why supposedly shrinkable boxes refuse to shrink in other layout modes too, and the same `min-width: 0` remedy applies. Recognising the symptom ("one box is wider than its share and the container overflows") is worth more than memorising which layout mode you are in. ## How to diagnose it in ten seconds In devtools, look at the computed track sizes rather than the elements: if one `1fr` track reports a width larger than its siblings, the track's base size is content-driven and you are in this situation. Temporarily setting `minmax(0, 1fr)` and watching the overflow disappear confirms it. If the overflow persists, the culprit is a fixed width or a padding sum inside the item, not the track floor. ## Why the default is this way It is deliberate: silently shrinking a track below its content's minimum would clip or overlap content by default, which is worse than an overflow you can see. CSS chooses visible breakage over invisible data loss, and asks you to opt in to the zero floor when you know clipping or wrapping is acceptable.

  • Why does overflow: hidden on the grid item also fix the overflowing column?
    Because the automatic minimum size only applies to items whose `overflow` is `visible`. Setting `hidden`, `auto`, `scroll` or `clip` makes the item a scroll container, and its `auto` minimum resolves to zero instead of its min-content contribution, so the track is free to shrink. It works, but it also clips anything that used to escape the box, so use it when the clipping is intended.
  • Why does text-overflow: ellipsis so often fail on a grid item?
    The item never gets narrow enough for text to overflow in the first place. Its automatic minimum size keeps the box as wide as the longest unbreakable run, so there is nothing to truncate. Add `min-width: 0` (or size the track `minmax(0, 1fr)`) alongside the usual `overflow: hidden`, `white-space: nowrap` and `text-overflow: ellipsis`, and the ellipsis appears.
  • Does minmax(0, 1fr) risk squashing content to nothing?
    It removes the content-driven floor, so yes — the track can shrink to whatever the free-space split gives it, and content narrower than that will overflow the item rather than the grid. That is usually the trade you want, because the overflow is now contained in one cell instead of breaking the page layout, but pair it with wrapping or clipping so the content still behaves sensibly.

saying these in an interview costs you the question

  • Says fr sets both the minimum and maximum width
  • Claims the browser is buggy or the content is at fault
  • Only adds overflow-wrap without a zero minimum
  • Thinks min-width: 0 on the container fixes it
  • Believes minmax(0, 1fr) and 1fr are identical

context