I have a CSS grid with a row div
for a header, a row div
for content, and a row div
for a footer. I want the content to fill the screen but keep the header and footer visible. I have a fixed-size div
inside another div
inside the content div
. Everything except the fixed-size div
is height: 100%
.
If I apply overflow-y: auto
to the content div
, the scrollbar appears on the content div
. This is great, but what I really want is for the scrollbar to appear on the div
inside the content div
instead.
https://jsfiddle.net/t08u9wnk/2/
How can I achieve my desired behavior of having the scrollbar appear on the div
inside the content div
while maintaining a responsive layout? What am I not understanding about height: 100%
in this scenario?
Browser: Microsoft Edge 103.0.1264.62
CodePudding user response:
I think the approach you are trying to follow would work only if you set a fixed height
or max-height
to div.grid-content > div
. Now the problem is that the height of this container is dynamic and depends on height: 100%
, so you might be tempted to do max-height: 100%
but here is a good reason for why this is not possible.
If you want div.grid-content > div
to have a scroll and keep the layout of the entire page based on the height of the screen, I'd propose you to use an absolute positioned overlay.
Here is a modified snippet of your code explaining how it works:
html, body {
height: 100%;
width: 100%;
}
body {
/* prevents scroll on the entire page */
overflow: hidden;
}
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div.grid {
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 1fr;
height: 100%;
width: 100%;
}
div.grid-header, div.grid-footer {
background-color: #ff0000;
}
div.grid-content {
background-color: #00ff00;
/* set relative positioning to contain absolute child */
position: relative;
}
div.grid-content > div {
/* this is strategy for creating a container that adapts to the size of its relative parent using absolute positioning without the need of setting a fixed height to div.grid-content */
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* add scroll on y axis */
overflow-y: auto;
}
div.grid-content > div > div {
height: 200vh;
width: 50%;
background-color: #0000ff;
}
<div >
<div >
<h3>
hi
</h3>
</div>
<div >
<div>
<div>
asdf
</div>
</div>
</div>
<div >
<h3>
bye
</h3>
</div>
</div>
CodePudding user response:
I have been bitten by this unintuitive design choice of CSS grid: https://github.com/w3c/csswg-drafts/issues/1777
In summary, CSS grid "1fr"
behaves like minmax(auto, 1fr)
(where 1fr
is the actual fractional dimension of the grid). The minimum width/height of a "1fr"
grid row/column is the auto
width/height. If the auto
width/height is larger than 1fr
, the whole row/column will expand out past 1fr
because minmax
ignores the max
when min > max
!
This is why my problem has the same symptoms as all the other questions about height: 100%
not working where the answer was that they had an ancestor with height: auto
. It turns out 1fr
can become auto
!
Replacing:
grid-template-rows: auto 1fr auto;
with:
grid-template-rows: auto minmax(0, 1fr) auto;
fixes the problem.