2

I have a site with dynamic content on which I want one section to fill the remaining height of the screen, but the caveat is that if the content in that section would cause the height of the page to exceed the viewport height, I want to stop the height of the section it at the bottom edge of the screen and add a vertical scrollbar for just that section.

I'm using CSS Flexbox. Here's a very simplified version of the markup and CSS:

body, div, h1, h2, html, p {
  margin: 0;
  padding: 0;
}

body,
html {
  height: 100%;
}

.siteContainer {
  background: gold;
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.contentContainer {
  background: lightblue;
  display: flex;
  flex: 1;
  flex-direction: column;
}

.subcontentContainer {
  background: pink;
  flex: 1;
  overflow-y: scroll;
}
<div class="siteContainer">
  <h1>Header</h1>
  <div class="contentContainer">
    <h2>Subheader</h2>
    <div class="subcontentContainer">
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
    </div>
  </div>
</div>

Assuming your screen has some height to it, you should see the pink section take up most of the screen and the text should not be going vertically off the screen.

However, if you were to copy and paste the <p>Some text here.</p> part a bunch more times so that the text goes off the screen, then you will see that the viewport scrollbar is enabled.

Instead of the viewport scrollbar though, I want to stop the content at the bottom edge of the screen (presumably with overflow-y or something like that) and add a scrollbar to just the pink section and not have a scrollbar for the viewport.

Is this possible with only CSS, and if so, how? Thank you.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
HartleySan
  • 7,404
  • 14
  • 66
  • 119
  • possible guidance can be seen [**`here`**](https://stackoverflow.com/questions/55170715/three-row-modal-with-fixed-with-header-bottom-row-and-scrollable-middle-row/55194462#55194462) – kukkuz Mar 21 '19 at 18:10

2 Answers2

2

If you set overflow-y: hidden to body, the outer scrollbar disapears.

Set the height from body and the siteContainer to 100vh.

html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

body {
  margin: 0;
  padding: 0;
  height: 100vh;
  overflow-y: hidden;  
}

body,
div,
h1,
h2,
html,
p {
  margin: 0;
  padding: 0;
}

.siteContainer {
  background: gold;
  display: flex;
  flex-direction: column;
  min-height: 100%;
  height: 100vh;
}

.contentContainer {
  background: lightblue;
  display: flex;
  flex: 1;
  flex-direction: column;
}

.subcontentContainer {
  background: pink;
  flex: 1;
  overflow-y: auto;
}
<div class="siteContainer">
  <h1>Header</h1>
  <div class="contentContainer">
    <h2>Subheader</h2>
    <div class="subcontentContainer">
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
    </div>
  </div>
</div>
d-h-e
  • 2,478
  • 1
  • 10
  • 18
1

The problem boils down to this: flex: 1 in your code.

flex: 1 is a shorthand rule that translates to:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

Because you're using column-direction containers, flex-basis represents height. So you've set your flex items to height: 0.

But the overflow property can only work when the container has a set height.

From MDN:

In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.

Well, for some browsers, flex-basis: 0 may not be enough to satisfy those conditions, so an overflow will not occur.

To ensure that your layout works reliably across browsers, set a height (any height) on the overflow element. Add this to your code:

.subcontentContainer {
   flex: 1 1 1px;
 }

.siteContainer {
  background: gold;
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.contentContainer {
  background: lightblue;
  display: flex;
  flex: 1;
  flex-direction: column;
}

.subcontentContainer {
  background: pink;
  flex: 1 1 1px; /* ADJUSTMENT */
  overflow-y: auto;
}

body,
div,
h1,
h2,
html,
p {
  margin: 0;
  padding: 0;
}
<div class="siteContainer">
  <h1>Header</h1>
  <div class="contentContainer">
    <h2>Subheader</h2>
    <div class="subcontentContainer">
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
      <p>Some text here.</p>
    </div>
  </div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701