I need to create a table with fixed <thead> and <tfoot> elements, but a <tbody> that varies in height as the browser window is resized and scrolls. The header should stick to the top of the container, and the footer to the bottom.
Doing this with a fixed height table isn’t a problem, but getting the overflow to work with a variable height table isn’t working under IE, and the footer is disappearing under FF.
I’d like to do this with a CSS-only solution, but I haven’t had any luck solving this. I’m sure I’m missing an obvious solution, so before I break out the Javascript…is there a better approach?
Target browsers: IE7+, FF3.5+, Safari 4.
Simple example code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en-US">
<head>
<title>Example Code</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<style type="text/css">
* {margin:0;padding:0;}
html,body {height:100%;overflow:hidden;}
table {width:990px;height:100%;empty-cells:show;border-collapse:collapsed;border-top:2px solid #CCC;border-left:2px solid #CCC;}
caption {display:none;}
tbody {height:100%;overflow:auto;}
th,td {line-height:4em;border-right:1px solid #CCC;border-bottom:1px solid #CCC;}
td {text-align:center;vertical-align:top;}
div {width:990px;height:100%;background:#DEF;margin:0px auto;}
</style>
<body>
<div>
<table cellspacing="0" cellpadding="0" summary="Results of Property Listing Search">
<caption>Search Results</caption>
<thead>
<tr>
<th scope="col" id="hdr_01">ID</th>
<th scope="col" id="hdr_02">Address</th>
<th scope="col" id="hdr_03">City</th>
</tr>
</thead>
<tfoot>
<tr>
<td id="ftr_01"></td>
<td scope="row" id="ftr_02" colspan="2">
<div>
Should stick at bottom of page.
</div>
</td>
</tr>
</tfoot>
<tbody>
<tr><td scope="row">0</td><td>Property 0</td><td>New York</td></tr>
<tr><td scope="row">1</td><td>Property 1</td><td>Milan</td></tr>
<tr><td scope="row">2</td><td>Property 2</td><td>Tokyo</td></tr>
<tr><td scope="row">3</td><td>Property 3</td><td>Liverpool</td></tr>
<tr><td scope="row">4</td><td>Property 4</td><td>Los Angeles</td></tr>
<tr><td scope="row">5</td><td>Property 5</td><td>London</td></tr>
<tr><td scope="row">6</td><td>Property 6</td><td>Athens</td></tr>
<tr><td scope="row">7</td><td>Property 7</td><td>Columbus</td></tr>
<tr><td scope="row">8</td><td>Property 8</td><td>Paris</td></tr>
<tr><td scope="row">9</td><td>Property 9</td><td>Chicago</td></tr>
</tbody>
</table>
</div>
</body>
</html>
Two-table solution that works a little better, but loses the connection between the header / footer and the body…
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en-US">
<head>
<title>Example Code</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<style type="text/css">
* {margin:0;padding:0;}
html,body {height:100%;overflow:hidden;}
table {width:990px;height:100%;empty-cells:show;border-collapse:collapsed;}
caption {display:none;}
#tbl1 {border-top:2px solid #CCC;border-left:2px solid #CCC;}
#tbl1 tbody {height:100%;overflow:auto;}
th,td {line-height:4em;border-right:1px solid #CCC;border-bottom:1px solid #CCC;}
td {padding:0px;text-align:center;vertical-align:top;}
div {height:100%;background:#DEF;}
#wrap {width:990px;margin:0px auto;}
#scrl {overflow:auto;}
#tbl2 {width:100%;}
</style>
<body>
<div id="wrap">
<table cellspacing="0" cellpadding="0" id="tbl1" summary="Results of Property Listing Search">
<caption>Search Results</caption>
<thead>
<tr>
<th scope="col" id="hdr_01">ID</th>
<th scope="col" id="hdr_02">Address</th>
<th scope="col" id="hdr_03">City</th>
</tr>
</thead>
<tfoot>
<tr>
<td id="ftr_01"></td>
<td scope="row" id="ftr_02" colspan="2">
<div>
Should stick at bottom of page.
</div>
</td>
</tr>
</tfoot>
<tbody>
<td colspan="3">
<div id="scrl">
<table cellspacing="0" cellpadding="0" id="tbl2" summary="Properties matching your criteria">
<tbody>
<tr><td scope="row">0</td><td>Property 0</td><td>New York</td></tr>
<tr><td scope="row">1</td><td>Property 1</td><td>Milan</td></tr>
<tr><td scope="row">2</td><td>Property 2</td><td>Tokyo</td></tr>
<tr><td scope="row">3</td><td>Property 3</td><td>Liverpool</td></tr>
<tr><td scope="row">4</td><td>Property 4</td><td>Los Angeles</td></tr>
<tr><td scope="row">5</td><td>Property 5</td><td>London</td></tr>
<tr><td scope="row">6</td><td>Property 6</td><td>Athens</td></tr>
<tr><td scope="row">7</td><td>Property 7</td><td>Columbus</td></tr>
<tr><td scope="row">8</td><td>Property 8</td><td>Paris</td></tr>
<tr><td scope="row">9</td><td>Property 9</td><td>Chicago</td></tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>