I'm trying to create a layout that looks something like this:
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:
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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With