Frozen table header inside scrollable div

59,860

Solution 1

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; }

Solution 2

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

Solution 3

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>

Solution 4

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.

Solution 5

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.

Share:
59,860
rafek
Author by

rafek

:-)

Updated on August 28, 2022

Comments

  • rafek
    rafek over 1 year

    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?

  • rafek
    rafek over 15 years
    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
    rafek over 15 years
    I've checked this. It works - but I can't call it "the solution" of this problem.
  • LeBleu
    LeBleu almost 15 years
    The linked example no longer exists. I had trouble getting this working, and went with the "Stupid Fixed Header" solution mentioned below.
  • Hemant Tank
    Hemant Tank over 14 years
    I 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.
  • scunliffe
    scunliffe over 13 years
    do you have a URL to the script as well? the link seems to only force a save of an HTML file only.
  • Steve Jansen
    Steve Jansen over 10 years
  • ManiMuthuPandi
    ManiMuthuPandi about 8 years
    It takes more time( or crash the browser) to load when table is so longer. I tried for 90 * 52 rows and columns.