I want to size a div
element to fill all remaining space available to it. However, if/when its contents exceed the remaining space, any overflow should be contained within without resizing or changing it's height. The element should have a fixed height which fills the remaining space.
My example is using Bootstrap.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<div class="row mx-0 flex-grow-1">
<div class="d-flex col-4 flex-column h-100 border border-dark">
<!--This column should expand down with its parent but never be able to expand off the screen-->
<div class="row py-2">
<div class="col">
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Friends</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Friend Requests</a>
</li>
</ul>
</div>
</div>
<div class="row flex-grow-1 overflow-auto">
<div class="col flex-column">
<!--If this list takes up more space than it's parents, it should overflow scroll without changing its height -->
<ul class="list-group-flush" style="padding: 0;">
<li class="list-group-item">
<h3 class="col lead">Friend</h3>
</li>
<li class="list-group-item">
<h3 class="col lead">Friend</h3>
</li>
</ul>
</div>
</div>
</div>
<!--Chat-->
<div class="col-8 flex-column h-100 border-top border-end border-bottom border-dark">
</div>
</div>
In this image, the above code rendered, the red box is the area of the screen that the above code is affecting. The length "x" height of the red square (badly drawn) should never be any less nor more than the screen height minus the combined heights of all other elements on the screen.
I want the element sizes to remain the same and the list should scroll within its parent column instead.
I can almost achieve the desired effect by setting the max-height to 520px: <div class="row mx-0 flex-grow-1" style="max-height: 520px;">
This gives a good idea of what I want to achieve.
However, I'm hoping to find a responsive solution that works regardless of screen height.
After applying @RokoC.Buljan answer to my work I had the following layout. Note the desired nested scroll-able areas. Thanks again for the help. Example is using Bootstrap 5.1
html {
font-size: 14px;
position: relative;
height: 100%;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
.site-root {
display: grid;
grid-template-rows: auto 1fr auto;
height: 100%;
}
.footer {
position: static!important;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<body class="site-root h-100">
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<h3>Header</h3>
</div>
</nav>
</header>
<main class="container d-flex flex-column flex-grow-1 overflow-hidden">
<div class="row"><h1>Jumbotron</h1></div> <!--Hub Jumbotron-->
<div class="row flex-grow-1 overflow-auto" style="flex-flow:nowrap;">
<div class="col-3 flex-grow-1 overflow-auto">
<!--Left Side Panel-->
<h3>Left Panel</h3>
</div>
<div class="col-9 d-flex flex-column flex-grow-1">
<div class="row"><h3>Hub Nav</h3></div> <!--Hub Nav-->
<div class="row flex-grow-1 overflow-auto" style="flex-flow:nowrap;">
<div class="col-3 d-flex flex-column flex-grow-1">
<!--Friend List-->
<div class="row"><h4>Friends List</h4></div>
<div class="row flex-grow-1 overflow-auto" style="flex-flow:nowrap;">
<div class="col flex-column flex-grow-1 overflow-auto">
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
<div class="p-2">Friend</div>
</div>
</div>
</div>
<div class="col-9 d-flex flex-column-reverse flex-grow-1">
<!--Chat-->
<div class="row"><h4>Message Bar</h4></div>
<div class="row flex-grow-1 overflow-auto" style="flex-flow:nowrap;">
<div class="col flex-grow-1 overflow-auto">
<p style="height:300vh;">1. Some paragraph to force scrollbars...</p>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<footer id="site-footer" class="border-top footer">
<div class="container">
<h3>Footer</h3>
</div>
</footer>
</body>
If I got you right, all you need to do is to flex
the desired items, and don't forget to set overflow: auto;
to the ones you want to independently scroll:
* { margin: 0; box-sizing: border-box; }
body {
height: 100vh;
display: flex;
flex-flow: column nowrap;
overflow: hidden;
}
.flex {
flex: 1;
overflow: auto;
}
.row {
display: flex;
flex-flow: row nowrap;
}
.cell-3 { flex-basis: 25%; }
.cell-9 { flex-basis: 75%; }
<header class="row" style="background: #bf0">
HEADER<br>
WELCOME!
</header>
<main class="row flex">
<section class="cell-3 flex" style="background: #0bf">
<p style="height: 200vh">Some paragraph to force scrollbars...</p>End.
</section>
<section class="cell-9 flex" style="background: #f0b">
<p style="height: 300vh">Some even taller paragraph as well...</p>End.
</section>
</main>
<!-- PS avoid inline `style`. The above is just for demo -->
which is basically an extension of this answer: Flex max height content with dynamic header and footer