2008-07-18

A simple HTML-CSS scrolling data box with fixed column headers

I have a number of web pages where large tables of data are presented, and I wanted a way to display them so that when the user scrolled through the data the column headers would stay fixed and not scroll out of view.

My solution was to create a div with a fixed height and width and with its overflow property set to scroll, and then put the actual data table inside that div. Then I put the column headers in a completely separate table outside and right before the div. This way the column headers stay fixed on the page and the user can use the scroll bar that appears on the data div to scroll through the data without moving the whole web page.

The toughest challenge was figuring out how to get the column headers to consistently line up properly with the data columns, since the default behavior for HTML tables is for the columns to be sized based on the data in each cell, and so left to their own devices the columns of the data table would be different each time your data changed.

Just setting the width property of the table cells in CSS, alone, did not work since it appears to me that the default behavior is ignore the width property on td elements. After a lot of trial and error I discovered that the following combination appears to work for me:

- In CSS set the table-layout property for the data and column header tables to fixed.

- In CSS set the width properties for both the data and column header tables to be some value which is less than or equal to the sum of all of the column widths. If you don't do this (i.e. just leave the table width property blank or set it to more than the sum of the column widths) then the columns will not stay fixed in at least Firefox 2, though it will probably still work in IE7. I think this is because in FF2 even if you set table-layout: fixed in CSS it will expand the cells as needed to take up the whole width of the table, and if you don't set the table's width explicitly it will inherit the width of the div it is inside.

- Create a CSS class for each column and set the width property for each column to the right number of pixels, and then give each td of both tables the appropriate class.

Here is rough outline of the code elements. This particular code is not designed to be fully cut and paste, and its air-code, so just use it to understand the idea:


CSS

div.datagrid
{width: 1000px;
height: 400px;
overflow: scroll;
border: 1px solid black;
font-size: 11px;}

table.headers_and_data
{border: 1px solid black;
border-collapse: collapse;
table-layout: fixed;
width: 980px}

td.col_0
{width: 71px}

td.col_1
{width: 150px}

td.col_2
{width: 300px}

td.col_3
{width: 478px}

HTML

// Output column headers table
<table border="1" class="headers_and_data">
<tr>
<td class="col_0">Column 0</td>
<td class="col_1">Column 1</td>
<td class="col_2">Column 2</td>
<td class="col_3">Column 3</td>
</tr>
</table>

//Start a new div with specified height and overflow set to scroll so that table
// of items is scrollable (see style for this div) and then start data table.
<div class="grid">
<table border="1" class="headers_and_data">
<tr>
<td class="col_0">Mississippi</td>
<td class="col_1">Jackson</td>
<td class="col_2">Delta swamps</td>
<td class="col_3">Possum</td>
</tr>
</table>

2 comments:

Jay said...

Thanks, this was the best fixed header scrolling table layout I could find after searching for hours. I thought about this concept before finding your page and didn't like the idea of fixed column widths, but hey, it's working.

Angeline Lee said...

How do i fix the overflow: scroll thing with particular height and width but not like the one in my blog? Thanks.