Reputation: 33
I have two CSS-Grids. One within the other. I don't want the whole page to scroll, but only the contents of a grid-area of the nested grid. This nested grid should fill all available space. However overflow:scroll
does not work within this nested grid.
As you can see in the simplified example below, the div with the class .aside
works perfectly while the div with .bottomleft
does not scroll at all.
The div-heights start to break with the .main-container
- div, but I have no idea why.
What really confuses me is why everything works fine in the .aside
- div. The only difference that I can see here is that it is not in the nested grid.
Naturally, everything works perfectly if the .bottom-left
- div or the second row of the .main-container
- grid are given a fixed height, but the goal is to make it variable.
I also tried adding various max-heights
and heights
to other parent divs, but was not successful so far.
Thank you!
https://jsfiddle.net/vs6c4gq9/3/
html,
body {
height: 100%;
overflow: hidden;
}
#root {
height: 100%;
}
.container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: auto auto;
grid-template-areas: 'nav nav ' 'aside main';
height: 100%;
}
.header {
grid-area: nav;
background-color: lightblue;
}
.main {
grid-area: main;
background-color: lightpink;
height: 100%;
}
.aside {
grid-area: aside;
overflow-y: scroll;
}
.main-container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: auto auto;
grid-template-areas: 'topleft topright' 'bottomleft bottomright';
height: 100%;
}
.topleft {
grid-area: topleft;
}
.topright {
grid-area: topright;
}
.bottomleft {
grid-area: bottomleft;
overflow-y: scroll;
height: 100%;
}
.bottomright {
grid-area: bottomright;
}
<div id="root">
<div class="container">
<div class="header">
header
</div>
<div class="main">
<div class="main-container">
<div class="topleft">
topleft
</div>
<div class="topright">
topright
</div>
<div class="bottomleft">
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>last</div>
</div>
<div class="bottomright">
bottomright
</div>
</div>
</div>
<div class="aside">
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>last</div>
</div>
</div>
</div>
Upvotes: 3
Views: 2525
Reputation: 371113
You're right in the sense that there doesn't seem to be any reason why the scroll function works on one element (.aside
), but not on another (.bottomleft
). There doesn't appear to be any material difference. One element is a nested grid container. But that shouldn't matter.
However, if you look at the bigger picture, neither scrollbar should work.
The overflow
property normally requires a fixed length to generate a scroll bar. Without such a limit, the element simply expands to accommodate content, and there's no possibility for an overflow.
Such is the case in your code: Both overflow elements are set to height: auto
.
.container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: auto auto; <-- second row (where 'aside' is placed) is
set to content-based height
grid-template-areas: 'nav nav ' 'aside main';
height: 100%;
}
.main-container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: auto auto; <-- second row (where 'bottomright' is placed) is
also set to content-based height
grid-template-areas: 'topleft topright' 'bottomleft bottomright';
height: 100%;
}
Now refer to this rule, as described in MDN:
In order for
overflow
to have an effect, the block-level container must have either a set height (height
ormax-height
) orwhite-space
set tonowrap
.
Hence, the scroll function in your code should fail in both cases. The fact that one works in at least one browser suggests an anomaly or an intervention. In either case, I would suggest it's unreliable.
Consider a trade-off: Sacrifice some flexibility in return for more stability and security. Here is a modified version of your code:
.container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 25px calc(100vh - 25px); /* adjustment */
grid-template-areas: 'nav nav ' 'aside main';
height: 100vh;
}
.header {
grid-area: nav;
background-color: lightblue;
}
.main {
grid-area: main;
background-color: lightpink;
}
.aside {
grid-area: aside;
overflow-y: scroll;
}
.main-container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 25px calc(100vh - 50px); /* adjustment */
grid-template-areas: 'topleft topright' 'bottomleft bottomright';
}
.topleft {
grid-area: topleft;
}
.topright {
grid-area: topright;
}
.bottomleft {
grid-area: bottomleft;
overflow-y: scroll;
}
.bottomright {
grid-area: bottomright;
}
body {
margin: 0; /* remove default margins */
}
<div id="root">
<div class="container">
<div class="header">
header
</div>
<div class="main">
<div class="main-container">
<div class="topleft">
topleft
</div>
<div class="topright">
topright
</div>
<div class="bottomleft">
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>bottomleft</div>
<div>last</div>
</div>
<div class="bottomright">
bottomright
</div>
</div>
</div>
<div class="aside">
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>aside</div>
<div>last</div>
</div>
</div>
</div>
Upvotes: 2