Your CSS Grid Row Won't Scroll? The min-height: 0 Trap
A grid or flex child that should scroll instead shoves the whole layout taller. The one-line reason — min-height defaults to auto, not zero — and the fix.
Here’s a layout bug I’ve hit in every framework I’ve ever used, and it always
looks like the browser ignoring me. You build a column: a fixed header on top,
then a content area underneath that’s supposed to scroll. You give the content
area flex: 1 (or 1fr in a grid), set overflow: auto, drop in a long
list — and instead of scrolling, the list pushes the entire layout taller.
Your header scrolls off the top of the window. overflow: auto does nothing.
You check the overflow property three times. It’s right. The browser isn’t broken, and neither are you. You’ve hit one of the most quietly confusing defaults in CSS.
The setup that breaks
.app {
display: grid;
grid-template-rows: auto 1fr; /* header, then fill */
height: 100vh;
}
.content {
overflow: auto; /* should scroll... doesn't */
}
The flex version of the same bug:
.col { display: flex; flex-direction: column; height: 100vh; }
.list { flex: 1; overflow: auto; } /* should scroll... doesn't */
In both cases the scrolling region grows to fit its content and shoves
everything else around, as if overflow weren’t set at all.
Why it happens
A flex or grid item’s min-height defaults to auto, not 0 (same for
min-width). And auto, in this context, means “at least as tall as my
content.”
So your 1fr / flex: 1 track has two instructions that conflict: “share the
leftover space” and “never be shorter than your content.” The minimum-size
rule wins. The track refuses to shrink below the intrinsic height of
everything inside it, so it grows the container instead — and because the box
expanded to fit all the content, there’s no overflow left for overflow: auto
to scroll. The constraint quietly beats your sizing.
The fix
Set min-height: 0 on the item that should scroll:
.content { overflow: auto; min-height: 0; }
The catch that trips people the second time: it has to be on the whole
chain. Every flex or grid ancestor between the fixed-height root and the
scrolling element needs min-height: 0 too. Miss one — a wrapper <div> in
the middle that’s also a flex container — and the auto minimum reappears
there and re-inflates the layout. When a scroll region still won’t behave
after you’ve fixed the obvious element, walk up the tree and add it to every
flex/grid parent.
The horizontal twin: min-width: 0
The exact same default causes the other classic: a flex item that won’t
shrink or truncate. You put text-overflow: ellipsis on a label inside a
flex row, the text is long, and instead of an ellipsis it blows the row wider
than the container. Cause: min-width: auto won’t let the item shrink below
its content’s width. Fix: min-width: 0 on the flex item. Same bug wearing a
different hat.
Spotting it in two seconds
Three symptoms, one root cause:
- Something that should scroll grows the page instead.
overflow: auto/hidden“does nothing.”- A flex item with
text-overflow: ellipsisrefuses to truncate.
All three are min-height / min-width: auto doing exactly what the spec
says, which is rarely what you want inside an app layout.
Rule of thumb
When you build a fixed-height shell with scrolling regions inside it, add
min-height: 0 (and min-width: 0 anywhere you truncate) to every flex
and grid container in the chain, by default. It isn’t a hack — it’s
deliberately opting out of a default that exists for good reasons, just not
the ones that apply when you’re laying out an application.
Further reading
I’m Chris Moore — an independent developer and consultant in Henderson, NV, working under Grudged LLC. I build and rescue the operational systems small teams run on. If a layout bug like this has eaten your afternoon, get in touch.