Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML flex box layout - scrolled element won't stretch

Tags:

html

css

flexbox

I'm trying to create a layout that looks something like this:

enter image description here

Where the header and footer are pinned to the window and the blue area scrolls vertically if it needs space.

I thought display:flex would do it, and the code below gets close, but there is a problem. If you scroll that content area, it looks like this:

enter image description here

It appears that the divs for the "left nav" and "content" are chopped to the height of the their parent, even though that parent is scrollable.

var linesToAdd = 100;
var html = "";
for (var i=0; i<linesToAdd; i++) {
   html += i + "<br/>"
}
document.getElementById('content').innerHTML = html;
html {
  height: 100%;
}
body {
  margin: 0;
  display: flex;
  flex-direction: column;
  height:100%
}
#header, #footer {
  background: #ffa0a0;
  flex-shrink:0;
}
#mid {
  flex-grow: 1;
  background: #a08080;
  overflow-y: scroll;
  display: flex;
}
#leftnav {
  padding: 10px;
  background: #8a8;
}
#content {
  background: #88a;
  padding: 10px;
}
<!doctype html>
<html>
<body>
  <div id="header">Header</div>
       
  <div id='mid'>
    <div id='leftnav'>Left nav</div>
    <div id='content'></div>
  </div>
  <div id="footer">Footer</div>
</body>
</html>

Now, I can modify that slightly to make it work when the content is overflowing, but then it doesn't work when the content is smaller. I'm looking for something that stretches vertically to the footer, when content is small, but overflows without chopping the backgrounds when content is large.

// With 100 here it looks good, but with 5, you see it doesn't stretch vertically.
var linesToAdd = 5;
var html = "";
for (var i=0; i<linesToAdd; i++) {
   html += i + "<br/>"
}
document.getElementById('content').innerHTML = html;
html {
  height: 100%;
}
body {
  margin: 0;
  display: flex;
  flex-direction: column;
  height:100%
}
#header, #footer {
  background: #ffa0a0;
  flex-shrink:0;
}
#mid {
  flex-grow:1;
  background:#a88;
  overflow-y:scroll;
}
#leftnav {
  padding: 10px;
  background: #8a8;
}
#content {
  background: #88a;
  padding: 10px;
}
<!doctype html>
<html>
<body>
  <div id="header">Header</div>
       
  <div id='mid' style="">
    <div style="display:flex">
      <div id='leftnav'>Left nav</div>      
      <div id='content'></div>
    </div>
  </div>
  <div id="footer">Footer</div>
</body>
</html>
like image 549
Rob N Avatar asked Feb 01 '16 14:02

Rob N


1 Answers

You need to set height on HTML too.

The faux columns method can help you here: (method revisited with gradient, but multiple backgrounds would work too )

<html>
<style>
  html {
    height: 100%;
  }
  * {
    box-sizing: border-box;
  }
  body {
    margin: 0;
  }
  .headorfoot {
    background: #ffa0a0;
    flex-shrink: 0;
  }
</style>

<body style="display:flex;flex-direction:column;height:100%">

  <div class="headorfoot">
    Header
  </div>

  <div id='mid' style="flex-grow:1;background:linear-gradient(to right,#80A080 200px,gray 200px , gray 203px, #8080A0 203px);;overflow-y:scroll;  display:flex">
    <!-- <div style="display:flex"> -->
    <div style="padding: 10px;width:200px;">Left nav</div>
    <div style="width:3px;"></div>
    <div style="padding: 10px;background:#8080a0;flex:1">
      <script>
        for (var i = 0; i < 100; i++) {
          document.write(i + "<br/>");
        }
      </script>
    </div>
    <!-- </div> -->
  </div>
  <div class="headorfoot">
    Footer
  </div>
</body>

</html>

You may also want to use : position:sticky for the left nav, (polyfills exists if you think it useful )

html,
body {
  margin: 0;
  height: 100%
}
.headorfoot {
  background: #ffa0a0;
}
body {
  display: flex;
  flex-direction: column;
}
#mid {
  background: #8080a0;;
  display: flex;
  flex: 1;
  overflow: auto;
}
.scroll {
  flex:1;
  border-left:solid gray;
  
}
.nav {
  position:sticky;
  top:0;
}

/* demo purpose */
.scroll:hover br {
  float:left;
  display:none;/* where float doesn't work ... demo purpose only */
}
<div class="headorfoot">
  Header
</div>

<div id='mid'>

  <div class="nav" style="padding: 10px;background:#80a080">Left nav</div>
  <div class="scroll" style="padding: 10px;background:#8080a0;">
    <script>
      for (var i = 0; i < 100; i++) {
        document.write(i + "<br/>");
      }
    </script>
  </div>
</div>
<div class="headorfoot">
  Footer
</div>
like image 63
G-Cyrillus Avatar answered Sep 22 '22 14:09

G-Cyrillus