Geeks With Blogs
Freestyle Coding Programming in the Real World

I have created the world's greatest web control. OK, it's more like I reinvented the wheel. I present to you a cross-browser table with a fixed header and scrollable body.

Column 1 Column 2 Column 3  
Row A-1 Row A-2 Row A-3
Row B-1 Row B-2 Row B-3
Row C-1 Row C-2 Row C-3
Row D-1 Row D-2 Row D-3
Row E-1 Row E-2 Row E-3
Row F-1 Row F-2 Row F-3
Row G-1 Row G-2 Row G-3

The magic is in a bit of tomfoolery. There are actually a few stacked controls. The code is produced with the following:

<div style="
margin: 0; padding: 0; border-collapse: collapse; width: 519px; height: 100px; overflow: hidden; border: 1px solid black;"
>
<table style="
margin: 0; padding: 0; border-collapse: collapse; color: White; width: 517px; height: 20px; text-align: left; background-color: Blue;"
>
<colgroup>
<col width="200px"/>
<col width="150px"/>
<col width="150px"/>
<col width="16px"/>
</colgroup>
<tbody>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<th style="
margin: 0; padding: 0; border-collapse: collapse;"
>
Column 1
</th>
<th style="
margin: 0; padding: 0; border-collapse: collapse;"
>
Column 2
</th>
<th style="
margin: 0; padding: 0; border-collapse: collapse;"
>
Column 3
</th>
<th style="
margin: 0; padding: 0; border-collapse: collapse;"
>
 
</th>
</tr>
</tbody>
</table>
<div style="
margin: 0; padding: 0; border-collapse: collapse; width: 517px; height: 77px; overflow: auto;"
>
<table style="
margin: 0; padding: 0; border-collapse: collapse; width: 500px;"
>
<colgroup>
<col width="200px"/>
<col width="150px"/>
<col width="150px"/>
</colgroup>
<tbody style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row A-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row A-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row A-3
</td>
</tr>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row B-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row B-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row B-3
</td>
</tr>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row C-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row C-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row C-3
</td>
</tr>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row D-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row D-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row D-3
</td>
</tr>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row E-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row E-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row E-3
</td>
</tr>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row F-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row F-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row F-3
</td>
</tr>
<tr style="
margin: 0; padding: 0; border-collapse: collapse;"
>
<td style="
border: 1px solid lightgrey;"
>
Row G-1
</td>
<td style="
border: 1px solid lightgrey;"
>
Row G-2
</td>
<td style="
border: 1px solid lightgrey;"
>
Row G-3
</td>
</tr>
</tbody>
</table>
</div>
</div>

It doesn't look too impressive. After all, it's nothing more than some carefully stacked controls. However, there are a few features that make this worthwhile. The most important is cross-browser compatibility. We have tested this with IE7, IE8, IE9, IE10 Beta, FF3, Chrome, and Mac Safari1.

The other major issue is that this does not work on mobile browsers. We have tried with iOS and Android. The reason is quite simple. Mobile browsers don't have scroll bars. If you need to make this work on a mobile browser, your best bet is to load a separate style-sheet that undoes everything.

Issues aside, let's tear into this thing. I want to first point out the issues that are pretty standard. Just about everything has a style="margin: 0; padding: 0; border-collapse: collapse;". This kills the slight differences between browsers with margins, borders, spacing, and padding. This is also why most of the large, block elements have defined widths.

The next significant fact is the use of colgroup. Most of us dismiss this element when creating tables. However, it is one of the most effective ways to lock down column widths2. This is very important to us; we need our two tables to stay aligned.

Now that the widths are OK, we have to lock down the heights. This is almost the sole source of magic. First, we fix the height of the containing box. Then, we fix the height of the header. Finally, we give the remaining room to the containing block for the body, minus 3 pixels for cross-browser rendering. It is definitely worth nothing that the body table does not have a height specified. This is necessary.

The rest of the magic comes from the overflow styles. Our first overflow tag is on the main block. We set the overflow to hidden. This tells the browser to simply hide anything that doesn't fit in the box3. Then, we set the inner div to have an overflow of auto. This tells the div to display scroll bars if the table is bigger than the div4.

That, in a nutshell, does it. Yes, there are a lot of cool extras you can pile on this framework. The version I developed is extremely more advanced than this. However, the bosses on let me give away so much free code.

1There is a minor graphical glitch. Different browsers have different sized scroll bars. As such, there are a few pixels between the borders on a few browsers.
2If the cell has a single string longer than the width, it will push the column borders and keep things from aligning. However, if you keep your columns sized appropriately for your data, the table will just grow the row vertically.
3If you removed this and the border, the control would probably downgrade nicely to mobile browsers. However, it also would keep the control from looking like a nice cohesive control.
4If you want to keep the scroll bar visible, replace the overflow: auto with overflow-x: hidden; overflow-y: scroll;

Posted on Tuesday, April 19, 2011 8:21 PM CSS , HTML | Back to top


Comments on this post: Html Table with Fixed Header and Scrollable Body

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
This is just what I have been looking for, have been able to change it to do what I needed except the table is not deep enough. Can I be really cheeky and ask how I can make a longer list visable.
Left by Rob on Feb 01, 2013 5:29 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Sure. That entire problem is solved by the Height of the outer most div (the first line of the code sample.) This keeps the total visible area to 100px. The top table explicitly takes 20 pixels, and I give the rest to the bottom div, with 3 extra pixels taken away for cross browser rendering.

Basically, the outer div should have a Height of total screen real estate. The header table should stay 20 (unless you need more.) The inner div that surrounds the bottom table should have a Height of ( OuterDiv.Height - HeaderTable.Height - 3 ). The data table will then fill in as much room as given and overflow the rest.
Left by Chris Gardner on Feb 02, 2013 9:28 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
What about when the data in one td is large? I believe your example will squish the columns together and the illusion is broken :(
Left by Robert on Feb 28, 2013 2:34 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Granted, I haven't played around with this for quite some time. However, I believe that is the purpose behind the colgroup. Setting the colgroup with explicit column widths locks the columns. This keeps the render engine from resizing them.

If that didn't work, then you would probably have to explicitly set the overflow for the column you suspect would be large.
Left by Chris Gardner on Feb 28, 2013 2:50 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Rocks! Perfect... I tried several and this was the only one that worked with my requirements.

thanks
Left by tami on Apr 02, 2013 3:05 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
simple superb - fantastic:)
Nothing to review, this is great stuff thanks for sharing it:)
Left by Arun Kumar T on May 30, 2013 10:01 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
nice one...many thanks for sharing.
Left by Antaryami Bhanja on Jun 10, 2013 2:18 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Thanks for sharing. Was collating information for home use in one html file and found this very useful.
Left by Har on Jul 10, 2013 11:25 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Thanks for sharing.
Left by gowda on Aug 07, 2013 1:09 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
This is just having vertical scroll wat if one need both vertical and horizontal scrollable table
Left by shubham on Aug 10, 2013 1:13 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
look my solution http://scrolltable.blogspot.com
Left by Emil on Aug 21, 2013 2:32 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
@Emil

That's is a pretty elegant solution. I didn't notice a few times when you're pieces go out of sync, but mine has a few graphical gotchas, too.

Your solution used jQuery, which I avoid like the plague. Given that alone, there is plenty of room for both solutions. Thanks for the link.
Left by Chris Gardner on Aug 21, 2013 9:08 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
If it would highlight a row on mouse over it would PERFECTLY fit my needs! Thanks for the code
Left by Gaetan on Nov 15, 2013 4:46 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Hi I was trying to implement your step to achieve vertical scroll bar in jsp table. but I have issue. I could not able to set the table with tbody tr td width using colgroup. can you please help why td is not setting colgroup width.

Thanks in advance
Left by Sri on Sep 22, 2014 10:37 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
@Sri

Hmm, that is strange. Could you tell me what browser you are using? This article is over 3 years old, and I haven't tested it on newer browsers.
Left by Chris Gardner on Sep 22, 2014 11:24 AM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
Hi there,
Thanks for sharing.
I am looking for freezing the first column as well. I could freeze it used fixed position but then scrolling does not happen as expected.

Do you have any clue if you can just give some idea to try out? I am yet to try some similar combination of styles using classed. I am visualizing it as a 3 diff components on is leftmost column, and header and body just like u have used.

Thanks,
Gaurav
Left by Gaurav Joshi on Jul 10, 2015 1:35 PM

# re: Html Table with Fixed Header and Scrollable Body
Requesting Gravatar...
how to handle if we have more number of columns (nearly 30 columns) to be fixed at header?
Left by Nagaraju on Mar 08, 2016 4:22 AM

Your comment:
 (will show your gravatar)


Copyright © Chris Gardner | Powered by: GeeksWithBlogs.net