I have a layout where I have a scrollable list of items in the center, with some stuff above and below it in a column. The list should take up as much empty space as is available to it in the column (I don't want to specify a specific height on it), and should scroll when the empty space in the column is not enough to fit all the items.
Here is a JSFiddle of the situation.
Notice that with just a few item
s in the scroller
, it expands to fill the empty space in the column
(as is intended). But then if you add several more item
s to the scroller
, it expands to fit the entirety of its contents instead of staying at its original size, and then scrolling its overflowing contents; even though the it has overflow-y: scroll
set!
However, if you then set the scroller
to have a height
of 0
, the problem is fixed and the items scroll as is intended, with the scroller
at its original height before the extra items were added.
But WHY!? Can someone please explain to me what's going on here? Also, is there any consequences of this "solution" that I'm not seeing?
<div class="column">
<div class="title">Header</div>
<div class="scroller">
<div class="item">Child</div>
<div class="item">Child</div>
</div>
<div class="title">Footer</div>
</div>
,
.column {
display: flex;
flex-direction: column;
height: 200px;
}
.title {
height: 50px;
flex-shrink: 0;
}
.scroller {
flex-grow: 20;
flex-shrink: 0;
overflow-y: scroll;
}
.item {
height: 20px;
margin-top: 2px;
}
Some quick background for anyone who runs across this later:
Elements that have flex-grow
expand to take up x units of the available space minus the other flex content. In your case, .scroller
is the only one with flex-grow but the other flex elements have defined heights so their content takes up space.
Elements that have flex-shrink
contract as the space decreases. A zero value means they don't contract, a value >=1 allows scaling down.
However flex-shrink
ONLY works if the element DOES NOT also have a flex-grow
applied to it. Elements with both shrink & grow will only shrink to the size of their content
In your example, overflow doesn't kick in when the element is as big as the content (see above) which it is because you have both grow/shrink applied. Adding an explicit height (height: 0
) overrides the computed "content" height allowing the flex-shrink
to compress the element smaller than its content. This, in turn, makes the scrollbar work.
I don't know if this will cause any oddities at some point but it's an interesting solution to the problem and does seem to work pretty well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With