Home > Enterprise >  Overflow works on outer 100% height div but not inner 100% height div
Overflow works on outer 100% height div but not inner 100% height div

Time:08-02

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.

Scrollbar on content div

Scrollbar on whole page instead of inner div

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.

https://jsfiddle.net/t08u9wnk/3/

  • Related