Reputation: 1769
I'm sure this kind of question was asked before, but I really can't describe it exactly and concisely enough to let the search engine to understand me. So here we go:
To better explain my question I'm writing the code in tailwind style here. A stack snippet is also attached below:
<div class="root w-screen h-screen flex flex-col">
<div class="header h-[72px] w-full bg-red shrink-0"></div>
<div class="content grow">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
</div>
In this example, I would like to limit the height of the entire div.root
to 100vh
. However, because div.content
is very tall, it expands the body
that it shows a vertical scrollbar.
Well this is fairly easy to overcome, I only need to add scroll-y-auto
to div.content
. So the body scrollbar disappears, and div.content
shows a vertical scrollbar. Perfect.
However later on, I decided to split div.content
into two columns: both column shall have its own vertical scrollbar. Intuitively I changed the code to:
<div class="root w-screen h-screen flex flex-col">
<div class="header h-[72px] w-full bg-red shrink-0"></div>
<div class="content grow">
<div class="left overflow-y-auto">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
<div class="right overflow-y-auto">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
</div>
</div>
But this does not work at all, as the attached snippet demonstrates. body
got its scrollbar back, but not div.left
or div.right
.
I've explored several ways to solve this problem. In the end the best solution I got was to set the height of div.content
to calc(100% - 72px)
. This works perfectly, but I understand it's only because I know the exact height of div.header
is fixed at 72px
.
Was I doing something wrong here? What's the most elegant way to solve this kind of problem?
body {
margin: 0;
}
.root {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.header {
height: 72px;
width: 100%;
background-color: red;
flex-shrink: 0;
}
.content {
flex-grow: 1;
display: flex;
flex-direction: row;
}
.very-tall-content {
background-color: green;
height: 2400px
}
.left, .right {
flex-grow: 1;
margin: 0 4px;
overflow-y: auto;
}
<div class="root">
<div class="header"></div>
<div class="content">
<div class="left">
<p class="very-tall-content"></p>
</div>
<div class="right">
<p class="very-tall-content"></p>
</div>
</div>
</div>
Upvotes: 0
Views: 1160
Reputation: 643
Allright, try this one maybe it fixed your problem :)
instead of using
flex
for.root
usegrid
. down here we have a header with minimum height of 72px and if it's content overloads, the header will auto-fit them
:root {
--header-min-height: 72px;
}
body {
margin: 0;
}
.root {
display: grid;
grid-template-rows: minmax(var(--header-min-height), auto) 1fr;
height: 100vh;
}
.header {
grid-row: 1;
background: darkcyan;
}
.content {
grid-row: 2;
display: flex;
background-color: palegreen;
overflow-y: hidden;
}
.content>div {
flex-grow: 1;
overflow-y: auto;
}
.white-space {
height: 3000px;
}
<div class="root">
<div class="header"></div>
<div class="content">
<div class="left">
Left Side
<div class="white-space"></div>
Left Side
</div>
<div class="right">
Right Side
<div class="white-space"></div>
Right Side
</div>
</div>
</div>
here's the example if it overloads.
:root { --header-min-height: 72px; } body { margin: 0; } .root { display: grid; grid-template-rows: minmax(var(--header-min-height), auto) 1fr; height: 100vh; } .header { grid-row: 1; background: darkcyan; } .content { grid-row: 2; display: flex; background-color: palegreen; overflow-y: hidden; } .content>div { flex-grow: 1; overflow-y: auto; } .white-space { height: 3000px; } .row { display: flex; flex-direction: row; width: fit-content; } .item { background: rgba(255, 255, 255, .5); width: fit-content; padding: 10px; margin: 5px; border-radius: 5px; }
<div class="root"> <div class="header"> <div class="row"> <div class="item">test</div> <div class="item">test</div> <div class="item">test</div> </div> <div class="row"> <div class="item">test</div> <div class="item">test</div> <div class="item">test</div> </div> <div class="row"> <div class="item">test</div> <div class="item">test</div> <div class="item">test</div> </div> </div> <div class="content"> <div class="left"> Left Side <div class="white-space"></div> Left Side </div> <div class="right"> Right Side <div class="white-space"></div> Right Side </div> </div> </div>
Upvotes: 1