I\'m attempting to build a layout that allows a flexible height header and footer, with a section in the middle consuming the remaining space. Any overflow in the middle sho
I think you ran into two combined problems here:
Table-dimensions aren't as fixed as you might expect it from a normal div. Tables usually grow with their content and don't care much about their height property if the content is too big.
Therefore you have to exclude the content of the scroll-box from the content-size calculation by position it absolutely. All that's now left to do is to set the position and size the scroll-box to fill the complete space of the expanded table-row. However, this raises another issue:
The straightforward solution would be to set position:relative;
for the table-row and width:100%;height:100%;
for the scroll-box, but this won't work because most browsers ignore the position-property of table-rows. You could insert another div with display:table-cell;position:relative;
between the table-row and the scroll-box, but this will only work for all browsers except Firefox, since Firefox doesn't allow any relative positioning within a table.
Firefox however allows relative positioning for the table itself, so the trick is to set position:relative;
for the table-div and set the size and the position of the scroll-box according to the dimensions of the whole table.
As you might expect this comes with some limitations if you want to use a pure CSS solution, but there are some anyway. Apart from that there's also an elegant way to solve the problem with JavaScript, which I've included in the code, too.
The code below includes three ways to solve your problem. Two are pure CSS solutions and one, which uses JavaScript. I've tried to change you code as less as possible and commented all changes, so I think you'll find you way through the lines. Leave a comment if you still have questions.
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.l-fit-height {
display: table;
height: 100%;
/* NOTE Use the table as refernece for absolute positioning. This */
/* is the only place where Firefox accepts the position property */
/* within a table. */
position: relative;
}
.l-fit-height > * {
display: table-row;
height: 1px;
background-color: red;
}
.l-fit-height-expanded {
/* NOTE Set the important flag to override the generic setting */
height: auto !important;
background-color: blue;
display: table-row;
}
.l-scroll-content {
/* NOTE We will set the height attribute later */
/* height: 100%; */
overflow-y: auto;
/* INFO Prevent the table from growing in height */
position: absolute;
/* INFO The content should span the full width */
width: 100%;
}
/* INFO Since Firefox only allows absolute positioning relative to the */
/* whole table, setting the correct height is a bit tricky. I've */
/* found two pure CSS solutions which work, but both have their */
/* glitches. If JavaScript is ok for you, there's another solution */
/* which I would recommend. */
/* INFO Example for percentage height footer and header. This sometimes */
/* leaves one or two pixels between the scroll-box and the footer. */
/* REMOVE THIS LINE TO ACTIVATE
.l-fit-height > * {
height: 20%;
}
.l-scroll-content {
height: 60% !important;
}
/**/
/* INFO Example for fixed height footer and header. Unfortunately this */
/* makes the header and footer-content unclickable, but I'm quite */
/* sure this could be solved by setting a z-index. */
/* REMOVE THIS LINE TO ACTIVATE
.l-fit-height > * {
height: 40px;
}
.l-scroll-content {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
height: 100%;
border-top: 40px solid transparent;
margin-top: -40px;
border-bottom: 40px solid transparent;
margin-bottom: -40px;
}
/**/
</style>
<script type="text/javascript">
// INFO Example how to fix the problem with JavaScript. This works for
// all kinds of heights (flexible, percentage and fixed) and has no
// issues except for the need of JavaScript to see a correctly
// layouted page.
//* REMOVE THE FIRST SLASH TO DEACTIVATE
function fixScrollContentHeight() {
var nodes = document.getElementsByClassName('l-scroll-content');
for (var i = 0; i < nodes.length; i++)
nodes[i].style.height = nodes[i].parentNode.offsetHeight+'px';
}
window.onload = fixScrollContentHeight;
window.onresize = fixScrollContentHeight;
//*/
</script>
</head>
<body>
<div class="l-fit-height">
<section>
Header
</section>
<section class="l-fit-height-expanded">
<div class="l-scroll-content">
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
</div>
</section>
<section>
Footer
</section>
</div>
</body>
</html>
PS: I wasn't able to test my code with IE, but I think it should work there, too.
I've discovered with a couple of extra div's and a crucial display: inline-block
it is possible to use the absolute positioning trick Torben mentions, in Firefox as well. This means that fully flexible header and footer is possible as a pure CSS solution.
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.l-fit-height {
display: table;
height: 100%;
}
.l-fit-height-row {
display: table-row;
height: 1px;
}
.l-fit-height-row-content {
/* Firefox requires this */
display: table-cell;
}
.l-fit-height-row-expanded {
height: 100%;
display: table-row;
}
.l-fit-height-row-expanded > .l-fit-height-row-content {
height: 100%;
width: 100%;
}
.l-scroll {
/* Firefox requires this to do the absolute positioning correctly */
display: inline-block;
overflow-y: auto;
position: relative;
}
.l-scroll-content {
position: absolute;
top: 0;
bottom: 0;
}
</style>
</head>
<body>
<div class="l-fit-height">
<section class="l-fit-height-row">
<div class="l-fit-height-row-content">
Header
</div>
</section>
<section class="l-fit-height-row-expanded">
<div class="l-fit-height-row-content l-scroll">
<div class="l-scroll-content">
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
</div>
</div>
</section>
<section class="l-fit-height-row">
<div class="l-fit-height-row-content">
Footer
</div>
</section>
</div>
</body>
</html>
Hope this helps
From here How to get firefox to show an auto horizontal scollbar for a div?
Firefox doesn't recognize overflow-x and overflow-y.
Instead use overflow:-moz-scrollbars-horizontal;
or overflow:-moz-scrollbars-vertical;
Please check my update.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
<style>
html, body {
height:99.9%;
margin:0;
padding:0;
}
#wrapper {
margin: auto;
overflow: hidden;
position: relative;
width: 99.9%;
}
#main {
margin-bottom: 67px;
margin-top: 77px;
overflow: auto;
padding-bottom: 80px;
}
#footer {
bottom: 0;
clear: both !important;
height: 75px !important;
margin-top: -68px !important;
position: fixed !important;
}
#header {
background: none repeat scroll 0 0 #FFFFFF;
border: 1px solid #000000;
height: 75px !important;
margin-top: -77px;
overflow: hidden;
position: fixed;
width: 100%;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="main">
<div id="header">header contents goes here</div>
<div id="content">
main contents
</div>
</div>
</div>
<div id="footer" style="width:99.9%; margin:auto; border:solid 1px #666; ">
Footer content goes here
</div>
</body>
</html>