Search code examples
htmlcssflexboxalignment

how to set html element such that it uses up remaining viewable vertical space


I'm struggling with getting the overflow-y piece to function as described in the code. I have an element that will only take up as much vertical space as its contents and when overflowing has the parent scroll. The code in its entirety can be seen here: https://jsfiddle.net/bmts8L5x/3/ . I've had to include only a part of the code here to satisfy the code to non-code ratio for the linter here.

header {
  background: yellow;
}

#first {
  overflow: hidden;
}

container {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

#side {
  display: flex;
  flex-direction: column;
  width: 200px;
  overflow: scroll;
}

#side>div {
  height: 200px;
}

html,
body {
  margin: 0;
  padding: 0;
}

main>div:first-child {
  background: white;
  height: 50px;
}

#big {
  background: pink;
  border: solid;
  overflow: scroll;
  display: flex;
  flex: 1;
}

#big>div {
  width: 1000px;
  height: 100px;
  /* I'd like to see #big take up the remaining space regardless of whether height here is 100px or 10000px */
}
<container>
  <div id="side">
    <div>
      side nav does not scroll
    </div>
    <div>
      item
    </div>
    <div>
      item
    </div>
    <div>
      item
    </div>
    <div>
      item
    </div>
    <div>
      item
    </div>

  </div>
  <div id="first">
    <header>
      foo
    </header>
    <main>
      <div>
        this should remain visible after scrolling without needing position fixed
      </div>
      <header>
        some other stuff
      </header>
      <div id="big">
        <div>
          this should take up the rest of the remaining viewable space and have any overflow be scrolled through.
          <br /> X scrolls as expected but Y's overflow isn't contained to rest of viewable space.
        </div>
      </div>
    </main>
  </div>
</container>


Solution

  • You can nest your flexboxes even more - make your #first and main a column flexbox and give height: 100% to it:

    #first, main {
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    

    See demo below:

    header {
      background: yellow;
    }
    
    #first {
      overflow: hidden;
    }
    
    container {
      display: flex;
      height: 100vh;
      overflow: hidden;
    }
    
    #side {
      display: flex;
      flex-direction: column;
      width: 200px;
      overflow: scroll;
    }
    
    #side>div {
      height: 200px;
    }
    
    html,
    body {
      margin: 0;
      padding: 0;
    }
    
    main>div:first-child {
      background: white;
      height: 50px;
    }
    
    #big {
      background: pink;
      border: solid;
      overflow: scroll;
      display: flex;
      flex: 1;
    }
    
    #big>div {
      width: 1000px;
      height: 100px;
    }
    
    
    /* ADDED */
    #first, main {
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    <container>
      <div id="side">
        <div>side nav does not scroll</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
      </div>
      <div id="first">
        <header>foo</header>
        <main>
          <div>
            this should remain visible after scrolling without needing position fixed
          </div>
          <header>
            some other stuff
          </header>
          <div id="big">
            <div>
              this should take up the rest of the remaining viewable space and have any overflow be scrolled through.
              <br /> X scrolls as expected but Y's overflow isn't contained to rest of viewable space.
            </div>
          </div>
        </main>
      </div>
    </container>