I've three divs. Header, central and footer. There is a table in central div (gridview) which is almost always longer than outer div. So I've made this div scrollable vertically. The question is: how can I make table header that it would be visible after div is scrolled down? I could have done this header with separate div or table and make it fixed but widths of columns in the table are not always the same - so I don't know how to maintain widths of columns in header then. Any clue?
11 Answers
I've just put together a jQuery plugin that does exactly what you want. Its very small in size and really easy to implement.
All that is required is a table that has a thead and tbody.
You can wrap that table in a DIV with a classname and the table will always resize to fit in that div. so for example if your div scales with the browser window so will the table. The header will be fixed when scrolling. The footer will be fixed (if you enable a footer). You also have the option to clone the header in the footer and have it fixed. Also if you make your browser window too small and all columns can't fit...it will also scroll horizontally (header too).
you just pass the DIV's classname to the plugin like so: $('.myDiv').fixedHeaderTable({footer: true, footerId: 'myFooterId'}); and the plugin will do the rest. FooterID is a element on the page that contains the mark-up for your footer. this is used if you want to have pagination as your footer.
If you have multiple tables on the page it will also work for each table you want to have a fixed header.
check it out here: http://fixedheadertable.mmalek.com/
Keep in mind its still 'beta' so I am adding new features and bug fixes daily.
Supported browsers: IE6, IE7, IE8, FireFox, Safari, and Chrome

- 5,680
- 2
- 25
- 26
-
It takes more time( or crash the browser) to load when table is so longer. I tried for 90 * 52 rows and columns. – ManiMuthuPandi Mar 30 '16 at 12:30
Solution is really simple. You need 3 DIVs: a general container (in my case of class "outer"), a table container (in my case of class "inner") and a DIV in which you make a clone of an existing table using jQuery or javaScript (in my case of class "header").
Solution uses CSS and a few lines of jQuery code, which clones HTML of "inner" into "header" and sets its width and height. Supports fixed and variable columns width. Tested with IE8, Firefox 9, Safari and Google Chrome.
Here is a sample code:
$(document).ready(function() {
$('.header').html( $('.inner').html() );
$('.header').css('width', $('.inner table').outerWidth() );
$('.header').css('height', $('.inner table thead').outerHeight() );
});
table {
width:100%;
}
th {
border-top:1px solid #999;
text-align:left;
}
td, th {
border-bottom:1px solid #999;
background-color:#EEE;
}
.outer {
position:relative;
width:500px;
}
.inner {
height:150px;
overflow:auto;
}
.header {
position:absolute;
top:0;
left:0;
overflow:hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="outer">
<div class="inner">
<table cellspacing="0" cellpadding="0">
<thead>
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>2</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>3</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>4</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>5</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>6</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>7</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>8</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>9</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>10</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>11</td><td>b</td><td>c</td><td>d</td></tr>
<tr><td>12</td><td>b</td><td>c</td><td>d</td></tr>
</tbody>
</table>
</div>
<div class="header">
</div>
</div>
</body>
Here is a basic solution using javascript:
function position(table) {
table.rows[0].style.position="absolute";
table.rows[0].style.top="0px";
table.style.marginTop = table.rows[0].clientHeight/1.2;
var widths = Array();
for(var i = 0; i < table.rows[0].cells.length; i++) {
widths[i] = max(table.rows[0].cells[i].clientWidth, table.rows[1].cells[i].clientWidth);
}
for(var row = 0; row < table.rows.length; row++) {
for(var col = 0; col < widths.length; col ++) {
table.rows[row].cells[col].style.width = widths[col] + "px";
}
}
}
function max(num1, num2) { return (num1 > num2) ? num1 : num2; }

- 1,928
- 3
- 27
- 51

- 4,401
- 8
- 42
- 52
-
The linked example no longer exists. I had trouble getting this working, and went with the "Stupid Fixed Header" solution mentioned below. – LeBleu Jul 13 '09 at 22:07
-
2I won't vote this one. It simply fixes each row to the top of the page not something that will work in a page which has anything more then just this table on the page. – Hemant Tank Jan 30 '10 at 07:05
-
Checkout http://meetselva.github.io/fixed-table-rows-cols/ , the accepted answer for http://stackoverflow.com/questions/296020/how-can-i-lock-the-first-row-and-first-column-of-a-table-when-scrolling-possibl – Steve Jansen Oct 09 '13 at 14:05
You would have to put the header outside the scrollable div. Everything within the div will scroll.
EDIT
Regarding the width if you go for a separate header, I can see a few solutions:
- Assuming this is dynamic content, generate "fixed" widths based on the length of the string. Obviously specify in terms of EMs and leave some margin for error.
- Use javascript.
- Use fixed width columns.
I haven't actually tried the first, and it might be overcomplicating things a bit. It's something to try if you're desperate for the effect though.
I should also mention that there are probably javascript libraries with table widgets that do this already. Have a look at them to see how they do it.

- 33,955
- 16
- 77
- 104
-
You are right but what about width of every column in header? Width of columns is not fixed and depends on data it changes. So how to maintain it when the header is separate? – rafek Jan 28 '09 at 05:43
You need to put a table with the headers about your table of data. You can maintain the column width with table-layout:fixed. JavaScript can be used to match the column widths.

- 7,233
- 12
- 42
- 53
Here's a nice solution (mostly CSS) which uses fixed width columns: http://www.imaputz.com/cssStuff/bulletVersion.html
And here's a bit of jQuery code to fix cell-widths when cell contents take more width than the fixed width:
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"
type="text/javascript"></script>
<script>
$(function() {
$('div.tableContainer').each(function() { // for each table
var div = $(this);
var widths = [];
var changed = false;
$('table>*>tr', div).each(function(tr_i) {
$(this).children().each(function(i) {
var w = $(this).width();
if (w > widths[i]) {
widths[i] = w;
changed = true;
}
});
}).each(function(tr_i) {
if (changed)
$(this).children().each(function(i) {
var width = widths[i];
// add some width for scrollbar
if (tr_i == 0 && changed && i == widths.length-1) width += 16;
// insert a div to ensure width
$(this).append('<div style="width:'+width+'px; height:0px"> </div>');
});
});
div.width(div.children('table').width()).css('overflow-x', 'hidden');
});
});
</script>
The output is a bit off in IE when using a non-strict DTD. Tweak the widths in the CSS if you can't use standards mode.
Note that the jQuery code increases the table width at the end, and disables the horizontal scrollbar. You may or may not want that.

- 10,323
- 2
- 20
- 11
You may try the jQuery plugin Stupid Fixed Header. The technique is basically the same: clone a header and put it on top of the table layer.

- 2,051
- 4
- 32
- 38
-
do you have a URL to the script as well? the link seems to only force a save of an HTML file only. – scunliffe Dec 08 '10 at 16:05
What you actually want to be doing is making the <tbody>
of the data table scrollable, so the <thead>
and <tfoot>
will remain naturally fixed.
Whilst this is trivial for FF et al:
tbody
{
height: 100px; /* or whatever */
overflow: auto;
overflow-y: auto;
overflow-x: hidden;
}
IE has severe and complex issues with tbody in general. It can be solved with expressions but it's non-trivial, and specific to the design.

- 74,572
- 17
- 113
- 180
I haven't tested this, but perhaps you could generate the table twice, once in the header and once in the scrolling div. Then in the header, make all the rows except the heading row invisible. Perhaps with 'display: none' or set their height to zero.

- 196
- 4
-
I've checked this. It works - but I can't call it "the solution" of this problem. – rafek Jan 28 '09 at 07:09
Take a look at YUI Data Table if you are looking for a comprehensive cross-browser implementation. I believe this is done by creating another table with matching column widths.
There appears to be tricks required to fix column widths. If I recall correctly, Firefox requires <col/> tags to be present.
In any case, there were many tricks employed in YUI DataTable (50k lines). You'd be well advised to look at it and decide how far you'd like to go on your own with this.

- 5,436
- 2
- 35
- 44
This solution works using CSS in Firefox and the other Gecko browsers, and CSS expressions in IE.
http://home.tampabay.rr.com/bmerkey/examples/nonscroll-table-header.html
The header and footer do not stay fixed in Opera or Safari/Chrome, but the whole table is scrollable so it is usable. Note that the columns are given percentage widths in the author's example, but they can be removed.
If you want to experiment with Opera/Safari/Chrome support, look at giving the tbody display:block and go from there.

- 6,800
- 2
- 23
- 17