This week I was tasked with styling a data table so that all the rows would scroll vertically, but the header row would stay in place. For the project in question, the scrolling must work in both Firefox and IE 7.
Firefox supports CSS for scrolling the <tbody> part of the table. However, IE does not support scrolling for the <tbody>. I searched some other blogs for solutions and found that a popular solution for IE involves using expressions in CSS. A scrolling <div> is placed around the <table>. The expression is applied to the <thead> row like this:
thead tr {
position: relative;
top: expression(this.offsetParent.scrollTop);
}
But I found that the relative positioning caused the <thead> to shift down a few pixels when the scroll is activated. (Adding -2 to the expression did not solve the shifting problem for me.) So I decided to use position: absolute instead. This positions the row in <thead> correctly, however it will cover up the rest of the table rows. So I applied extra padding to the first table row in <tbody>, so that the date will show below the fixed header. Here is the result:
Here is my code, which I have only tested in Firefox 3 and IE 7. The first CSS style block is for Firefox. The second style block is within conditional comments for IE, so that these styles will overwrite the Firefox styling. (Normally I would be linking to external stylesheets -- a general one for non-IE browsers and a separate one for IE). For simplicity's sake in this example, I did not use class names -- you could apply your own class names as needed.
CSS:
<style type="text/css">
table {
border: solid #66CC99;
border-width: 0px 1px 1px 0px;
width: 400px;
}
th, td {
border: solid #66CC99;
border-width: 1px 0px 0px 1px;
padding: 4px;
}
th {
background-color: #339999;
color: #FFFFFF;
}
tr.alt td {
background-color: #EEEEEE;
}
tbody {
height: 200px;
overflow-y: auto;
overflow-x: hidden;
}
</style>
<!--[if IE]>
<style type="text/css">
div {
position: relative;
height: 200px;
width: 416px;
overflow-y: scroll;
overflow-x: hidden;
border: solid #66CC99;
border-width: 0px 0px 1px 0px;
}
table {
border-width: 1px 1px 0px 0px;
}
thead tr {
position: absolute;
top: expression(this.offsetParent.scrollTop);
}
tbody {
height: auto;
}
table tbody tr:first-child td {
padding: 29px 4px 4px 4px;
}
</style>
<![endif]-->
HTML:
<div>
<table border="0" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th>HEADER 1</th>
<th>HEADER 2</th>
<th>HEADER 3</th>
<th>HEADER 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>content 1</td>
<td>content</td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 2</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr>
<td>content 3</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 4</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr>
<td>content 5</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 6</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr>
<td>content 7</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 8</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr>
<td>content 9</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 10</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr>
<td>content 11</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 12</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr>
<td>content 13</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
<tr class="alt">
<td>content 14</td>
<td>content </td>
<td>content </td>
<td>content </td>
</tr>
</tbody>
</table>
</div>