A developer will often get a requirement to query a database and return the results in an HTML table. If the number of records returned is a lot then the developer is asked to page the results (click here for the next 20 records). Paging is no fun, but it understandable that the user would not want to scroll to the point where they can't view the column headers. An ideal sitution is to return as much of the data as possible in format that the user can easily view and understand the data. Microsoft Excel allows users to fix column headers, this article explains how to do it HTML.
A Simple Solution
In HTML we can used a fixed width DIV to hold the data inside a TABLE. And we can restrict the height of the DIV to a pre-defined number of pixels. For space reasons, the examples below restrict the TABLE to 70 pixels. Setting the overflow attribute to auto will force the scrolling to take place inside the DIV. Now we can just code the column headers above the DIV in a separate TABLE. If the column header TABLE and the DIV have the same width it will appear as though the column headers are fixed.
<table width="400">
<tr>
<th>Name</th><th>City</th><th>1999 Sales</th><th>2000 Sales</th><th>2001 Sales</th>
<tr>
</table>
<div style="width:400; height:100; overflow:auto;border:" id="dataList">
<table width="380">
<!-- Add records here -->
</table>
</div>
Example 1
| Name | City | 1999 Sales | 2000 Sales | 2001 Sales |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
Getting the Columns Straight
In the above example the columns are a little crooked. They don't exactly line up. I tried use javascript to calculate the width of the data cells in order to draw fixed width column headers, but I couldn't get it to work. If anyone has been able to to do this please email me the code. In order for the column headers to line up straight, I did it the old-fashioned way: I hard coded the width of the table cells to match the width of the column headers.
Example 2
This is the same table with fixed width cells.
| Name | City | 1999 Sales | 2000 Sales | 2001 Sales |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
More Tips
Sometimes sizing everything perfectly can be difficult, especially if the data varies in length. Here are a few more tips to help achieve an Excel-like table in HTML.
table-layout:fixed - Dianliang Zhu alerted me to this CSS tag. By adding STYLE="table-layout:fixed;" to our table we can contain the browser cell to the width we define. However, if we don't define our cell widths, it will use the width of the first cells to determine the table layout. This is an excellent tag to use, so be sure to define the cell widths.
Fixed-Width Fonts - Counting characters can be a pain, especially when the size of each character varies in width. To eliminate this possibility consider using a fixed-width (aka Monospace) font such as Courier for the table.
Server-Side Data Trimming - To prevent long pieces of data from pushing out or streching a cell, perform some server-siding trimming. Do you need the full company name or would the first 30 characters be enough? (EX: companyName = Left(companyname,30))
Example 3 - Using More Tips
| Name | City | 1999 Sales | 2000 Sales | 2001 Sales |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
| Joe | Atlanta | $400,000 | $450,000 | $430,000 |
| Sue | Memphis | $500,000 | $550,000 | $455,000 |
| Matt | NYC | $300,000 | $350,000 | $330,000 |
| Lou | Akron | $200,000 | $150,000 | $130,000 |
| Ann | Austin | $400,000 | $450,000 | $430,000 |
Last Words
As expected, not every browser supports the
overflow feature. The ideal use of this would be for a corporate Intranet where users were restricted to a one standards-compliant browser.
This article was first written in 2002. For a different solution see Cross-browser scrolling tbody.Labels: CSS, HTML