Reputation: 103
I would like a grandchild from a flex container to have its max height contained by the total height of container (100%) minus the other child height, and then have scrollbars appear when the grandchild has reached its max size.
Here is a fiddle to show it, basically I do not want the list items to overflow the green container.
https://jsfiddle.net/gcdzL3jn/2/
body {
display: flex;
flex-direction: column;
height: 80vh;
}
#header {
background-color: red;
height: 30px;
}
#main {
background-color: green;
display: flex;
height: 100%;
flex-direction: column;
}
#panel {
height: 100%;
}
#panel-top {
height: 80px;
border-style: solid;
}
#panel-bottom-overflow {
border-style: solid;
overflow-y: auto;
}
#footer {
background-color: yellow;
height: 30px;
}
<body>
<div id="header">
</div>
<div id="main">
<div id="panel">
<div id="panel-top">
Top Panel
</div>
<div id="panel-bottom-overflow">
<ul>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
</ul>
</div>
</div>
</div>
<div id="footer">
</div>
</body>
Upvotes: 1
Views: 6640
Reputation: 87191
By giving main wrappers, body, #main, #panel
, display: flex;
with column direction, the children that should take the remaining space (#main, #panel, #panel-bottom-overflow
) flex: 1
and finally add an extra wrapper for the scrolling, your will end up with this.
The extra scroller
overcomes the issue where the overflowing element needs a height by using absolute positioning.
Note, this solution also makes it possible to drop the fixed height on both header, panel and footer (which I did, but you can of course add them back) and let it size by its content, and it will still work.
body, #main, #panel {
display: flex;
flex-direction: column;
}
#main, #panel, #panel-bottom-overflow {
flex: 1;
}
body {
height: 80vh;
}
#header {
background-color: red;
padding: 5px;
}
#main {
background-color: green;
}
#panel-top {
border-style: solid;
padding: 30px 5px;
}
#panel-bottom-overflow {
position: relative;
border-style: solid;
}
#panel-bottom-overflow .scroller {
position: absolute;
top: 0; left: 0;
right: 0; bottom: 0;
overflow: auto;
}
#footer {
background-color: yellow;
padding: 5px;
}
<div id="header">
Header
</div>
<div id="main">
<div id="panel">
<div id="panel-top">
Top Panel
</div>
<div id="panel-bottom-overflow">
<div class="scroller">
<ul>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
</ul>
</div>
</div>
</div>
</div>
<div id="footer">Footer
</div>
Upvotes: 6
Reputation: 371301
You need to define a height for the overflowing element. With a height limit in place, the overflow
property can be triggered. Add this to your code:
#panel-bottom-overflow { height: calc(100% - 80px); }
Your green container (#main
) has one child (#panel
). Both elements are set to height: 100%
.
The child element has two children: #panel-top
and #panel-bottom-overflow
.
#panel-top
is set to height: 80px
.
Without a height limit on the sibling, content can visibly overflow (overflow: visible
is the default setting), but overflow: auto
needs a set height or max-height
for scrollbars to work.
body {
display: flex;
flex-direction: column;
height: 80vh;
}
#header {
background-color: red;
height: 30px;
}
#main {
background-color: green;
display: flex;
height: 100%;
flex-direction: column;
}
#panel {
height: 100%;
}
#panel-top {
height: 80px;
border-style: solid;
}
#panel-bottom-overflow {
border-style: solid;
overflow-y: auto;
height: calc(100% - 80px); /* NEW */
}
* { box-sizing: border-box; } /* NEW */
#footer {
background-color: yellow;
height: 30px;
}
<body>
<div id="header">
</div>
<div id="main">
<div id="panel">
<div id="panel-top">
Top Panel
</div>
<div id="panel-bottom-overflow">
<ul>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
<li>List item</li>
</ul>
</div>
</div>
</div>
<div id="footer">
</div>
</body>
Upvotes: 2