Link to home
Start Free TrialLog in
Avatar of eirikur
eirikur

asked on

Table headers always visible

Hello,

I've got a nice table with ten columns and x rows (dynamically generated) and I want to make the table headers always visible, even if I'm scrolling down the page, but WITHOUT frames please !
The solution must be working on at least IE 5.

Thank you,
Avatar of dgelinas
dgelinas
Flag of United States of America image

You can make a table for the header consisiting of one row and a table for the body.  
ASKER CERTIFIED SOLUTION
Avatar of seanpowell
seanpowell
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
<SCRIPT language="JavaScript">
<!--

// creates functions to have table header
// scroll with the page.
   var scrollbase=0;
   var ELpntr=false;
   var resetval=0;
   var NS=(document.layers) ? true : false;
   var IE=(document.all) ? true : false;

   function DetectB()
   {
// most of the cross-browser stuff get taken care of here
      if (NS)
      {
         ELpntr=document.HeadTable;
      }
      else
      {
         ELpntr=document.all.HeadTable.style;
         ELpntr.ypos=parseInt(ELpntr.top);
         resetval=scrollbase;
      }
      resetROW();
   }

   function resetROW()
   {
      if(IE)
      {
         resetval = document.body.scrollTop;
         ELpntr.ypos = resetval;
         if(ELpntr.ypos >= 15)  // Change this 15
               {
                     ELpntr.top = (ELpntr.ypos - 15); // replace this 15 with the same number.
               }
         else
               {
                     ELpntr.top = scrollbase;
               }
         resetval = scrollbase;
      }
      else
      {
         eval(ELpntr.top)=eval(window.pageYOffset);
      }
      setTimeout('resetROW()',100);
   }
//-->
</SCRIPT>

<BODY onLoad="DetectB()">

<div ID="HeadTable" style=" position: relative;top: 0;left: 0;">


<table style="padding-left: 8px; border: 1px solid black;" border='0' cellspacing="0" cellpadding="0" valign="top" bgcolor="papayawhip">




      <tr bgcolor="##FE9900" style="color: white;" valign="bottom">
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
            <td>test</td>
      </tr>


</table>
</div>



<table style="padding-left: 8px; border: 1px solid black;" border='0' cellspacing="0" cellpadding="0" valign="top" bgcolor="papayawhip">


<tr>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
                  <td>test</td>
            </tr>

                        <tr>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
            </tr>

                        <tr>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
                              <td>test</td>
            </tr>

</table>

On the Javascript part you need to replace the "15" with the number of pixels down the header table is and also replace the "15" right below it with the same number. You can just randomly put numbers into it till you get it to the right number of pixels. After that the header will stay in place until the top of the screen hits it then it will move down with the screen.
Tim, I hope you realize that when I wrote that very old method, that it was only designed to support IE and Netscrap 4. It will not work for Mozilla or any orther modern browser except IE.

I don't know which thread you cut it from but I do appreciate aknowledgement.

Now for this to work with variable width heading there are a couple of approaches. The first is IE only and is IMHO really defective.  It can be made cross browser but by getting rid of the set expression and setting the with through the dom, but that is even more backward than the IE specific method. The second approach does not work for IE because they talk a good game on open standards, but have failed to support them every chance they get.  The second approach is elegant and clean, and looks gourgeious in Mozilla, and it is one of the reason we are moving our client off of IE to standardization on Mozilla 1.6.

The defective IE approach:

<html>
<head>
<script language="javascript">
window.onload = init;
function init() {
var eTable = document.getElementById("headers");
eTable.style.setExpression("width","document.getElementById('data').offsetWidth");
document.getElementById('th1').style.setExpression("width","document.getElementById('td1').offsetWidth");
document.getElementById('th2').style.setExpression("width","document.getElementById('td2').offsetWidth");
document.getElementById('th3').style.setExpression("width","document.getElementById('td3').offsetWidth");
document.getElementById('th4').style.setExpression("width","document.getElementById('td4').offsetWidth");
}
</script>
<style>
table#headers, table#data {table-layout:fixed;background:#dda0dd;}
td, th {vertical-align:top;background:#ffffff;}
</style>
</head>
<body>
<table cellpadding="4" cellspacing="1" id="headers">
<tr>
<th id="th1">Test</th>
<th id="th2">Hello</th>
<th id="th3">Yoohoo</th>
<th id="th4">Hmm</th>
</tr>
</table>
<div style="width:100%;height:300px;overflow:auto;">
<table cellpadding="4" cellspacing="1" width="100%" id="data">
<tr>
<td id="td1">Data</td>
<td id="td2">Hello</td>
<td id="td3">I am here and so are you</td>
<td id="td4">Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I...........................................xxxxxxxxxxxxxxxxxxxxxx</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
</table>
</div>
</body>
</html>



The better way:

<html>
<head>
<style>
td {padding:5px; }
</style>
</head>
<body>
<table style="width:600px" border="1" id="header">
<thead>
<tr>
<th>Test</th>
<th>Hello</th>
<th>Yoohoo</th>
<th>Hmm</th>
<th style="width:15px">&nbsp;</th>
</tr>
</thead>
<tbody style="width:600px;height:300px;overflow:auto;">
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are youuuuuuuuuuuuuuuuuuuuu</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Dataaaaaaaa</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are youuuuuuuuuuuuuuuuuuuuuuu</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
<tr>
<td>Data</td>
<td>Hello</td>
<td>I am here and so are you</td>
<td>Yoohoo</td>
</tr>
</tbody>
</table>
</body>
</html>

Cd&
First. Someone pointed me to that code a while back when I had a problem. I modified it some to meet my own needs. Had I known who I got it from and that they would be so angry about me helping out another person with it then I would have given you credit. As far as your solutions. The first one is great if he wants his data inside of a scrolling box. The second one as you stated doesn't work in IE with if you read his post he says "The solution must be working on at least IE 5." so that does him a lot of good.
That old approach is not very useful unless the only thing on the page is the table and that the desired position is the top of the page.  Try integrating it into another page or position it half way down the page.

It became obsolete as soon as the support for teh overflow property stablized.  The heading do not stay fixed.  They jump around because there is a latency between iterations of the positioning function.  It was alright in its day but so was was the 80286 processor.

What Sean posted, and what I posted support current standards.  Sean's is cross-browser. The first of mine can be made cross-browser.  I also address the problem of variable width data, and Sean's can be adapted to do to that.

BTW. for IE6 it might or might not work, depending on the doctype.  With a strict doctype, document.body.scrollTop no longer exists.  It must be referenced as document.documentElement.scrollTop

Cd&
what about this one Cd&?  THis one was yours...


<html>
<head>
  <title> scrollable table</title>
<style>
  body {background-color:moccasin}
  th {color:snow;background-color:darkkhaki}
  td {color:navajowhite;background-color:navy}
  .maindiv {background-color:tan}
</style>
<body>
  <div style="position:absolute;left:100;top:10">
     <table frame="border" width = 480>
        <col width=80>
        <col width=80>
        <col width=80>
        <col width=80>
        <col width=80>
        <col width=80>
        <tr>
           <th>first</th>
           <th>second</th>
           <th>third</th>
           <th>fourth</th>
           <th>fifth</th>
           <th>sixth</th>
        </tr>    
     </table>
     <div class="maindiv" STYLE="overflow-X:hidden;overflow-y:scroll;width:496;height:300;">
        <table frame="border" width=480 height=1200 >
        <col width=80>
        <col width=80>
        <col width=80>
        <col width=80>
        <col width=80>
        <col width=80>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
        <tr>
           <td height=60>Cd&</td>
           <td height=60>:^)</td>
           <td height=60>colC</td>
           <td height=60>xxxx</td>
           <td height=60>:^)</td>
           <td height=60>Cd&</td>
        </tr>
     </table>
  </div>    
  <table border=1 width=480 bgcolor="silver">
     <col width = 80>
     <col width = 80>
     <col width = 80>
     <col width = 80>
     <col width = 80>
     <col width = 80>
     <tr>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
        <th></th>
     </tr>    
  </table>
</div>
</body>
</html>
which was the one i posted, btw, when tim_cs asked HIS question on how to do this...


https://www.experts-exchange.com/questions/20844907/Table-header-needs-to-stay-in-place-on-page-while-scrolling-down.html
That will also work - it does use overflow-x and y though, which are MS only additions. There's probably countless variations on the theme.

1. A static and inflexible one that I posted above.
2. A more robust dynamic version using scripting that Cd& posted.

All depends on one's needs. Let's wait until we get a better idea of what the asker is looking for before we go any further :-)

Thanks,
Sean
The  overflow-x:hidden;overflow-y:scroll  came from IE4 support befroe non-IE browsers knew what it was.  Later got modified to overflow:auto;overflow-x:hidden when Netscrap/mozilla added support, but IE often insisted on putting in a horizontal scroll when it was not needed.  With modern browsers overflow:auto gets pretty consistent rendering.

Cd&
I still like the standards compliant tbody method and maybe by IE 9.4, MS will support the complex table model properly.

Cd&
Avatar of eirikur
eirikur

ASKER

Thank you for all your answers, I'll test them and reward the winners :)
Hi there!

I just found this topic and tried to find a solution which hasnt to much javascript in it!
So here is what i got. Try it! Works fine with IE5.01+ and Moz!

Have fun, fightbulc!

<html>
<head>
      <style type="text/css">
            body {
                  margin:0px;
                  padding:0px;
            }
      </style>
      <script type="text/javascript">
            
            function setWidth(headTable,bodyTable) {

                  tHeadObj = document.getElementById(headTable).getElementsByTagName('col');
                  tBodyObj = document.getElementById(bodyTable).getElementsByTagName('col');

                  for(i=0;i<tHeadObj.length;i++) {
                        
                        tBodyObj[i].style['width'] = tHeadObj[i].offsetWidth - (document.all ? 6:0);
                        
                  }
                  
                  window.onresize = function() { setWidth(headTable,bodyTable); }
                  
            }
            
      </script>
</head>
<body onLoad="setWidth('headTable','bodyTable')">

<table id="headTable" border="0" cellspacing="1" cellpadding="3" width="100%">

<col>
<col>
<col>

<tr>
      <td style="background:#ccc" onclick="alert(this.offsetWidth)" onmousedown="this.style['background'] = '#999'" onmouseup="this.style['background'] = '#ccc'">id</td>
      <td style="background:#ccc" onmousedown="this.style['background'] = '#999'" onmouseup="this.style['background'] = '#ccc'">firma</td>
      <td style="background:#ccc" onmousedown="this.style['background'] = '#999'" onmouseup="this.style['background'] = '#ccc'">anrede</td>
      <td style="background:#ccc" onmousedown="this.style['background'] = '#999'" onmouseup="this.style['background'] = '#ccc'">nachname</td>
</tr>
</table>

<div style="overflow:auto;height:100px;">

      <table id="bodyTable" border="0" cellspacing="1" cellpadding="3" width="100%">      

      <col>
      <col>
      <col>

      <tr>
            <td style="background:#fc0">id 1</td>
            <td style="background:#fc0">firma 1</td>
            <td style="background:#fc0">anrede 1</td>
            <td style="background:#fc0">nachname 1</td>
      </tr>
      <tr>
            <td style="background:#fc0">id 1</td>
            <td style="background:#fc0">firma 1</td>
            <td style="background:#fc0">ad adandlan ansldna ndandans daksnd 1</td>
            <td style="background:#fc0">nachname 1</td>
      </tr>
      <tr>
            <td style="background:#fc0">id 1</td>
            <td style="background:#fc0">firma 1</td>
            <td style="background:#fc0">anrede 1</td>
            <td style="background:#fc0">asdddddd asddddddddd addddddd dddddddddddddasd ad adghzhzjze 1</td>
      </tr>
      <tr>
            <td style="background:#fc0">id 1</td>
            <td style="background:#fc0">firma 1</td>
            <td style="background:#fc0">anrede 1</td>
            <td style="background:#fc0">nachname 1</td>
      </tr>
      <tr>
            <td style="background:#fc0">id 1</td>
            <td style="background:#fc0">firma 1</td>
            <td style="background:#fc0">anrede 1</td>
            <td style="background:#fc0">nachname 1</td>
      </tr>
      <tr>
            <td style="background:#fc0">id 1</td>
            <td style="background:#fc0">firma 1</td>
            <td style="background:#fc0">anrede 1</td>
            <td style="background:#fc0">nachname 1</td>
      </tr>
      </table>

</div>

</body>
</html>
hello, a stupid suggestion but will work on most browsers (from NN4, opera 5 or 6,  and IE5) and probably all the browsers to come in a near future.

the page is 3 elements :
- top of the page (if exists)
- headers of the table
- lines

i assume the width of a 10 cols table is the page's width

if you store the firt two in anchored div's and let the user scroll through the latter, you don't need ANY javascript for the page to work properly

if div1 is small, consider a fusion of div1 and div2, if not, consider to use a javascript to hide the first (or better : reduce it's size to 2px and use an onmouseover event to grow it again). if javascript is disabled in the client's browser, the table will still be readable.

you end up with a fully featured page wich will work on any browser in the wild apart from NN4.

note : such issues may be relevant only if the part of the page which is not in the table is small and does not need to be page-scrollable in the present nor in the future.
@skullnobrains: Can you post an example of your explaination?

I think its important to use javascript, cause of the same cell width between the header and body cells.
For me thats the big deal about the static table header.

Actually I would prefer a non javascript-version, but thats not possible, cause of the missing tbody-overflow for the IE!

Later,
fightbulc!
i went over the problem again, and unless u add some unsafe javascripting, it does not do the trick alright in iexplore
just for information, and since it might be usefull combined with the following link
http://javascriptkit.com/javatutors/static3.shtml

and here is the basic script for netscape

<html><body>
      <div ID="head" style="top:0;left:0;width:100%;height:25;background-color:red;position:fixed;">
      <table height="100%" bgcolor="green"><tr><td
                        onMouseOver="javascript:
                                                      document.getElementById('head').style.height=25;
                                                      document.getElementById('headers').style.top=25;"
                        onClick="javascript:document.getElementById('head').style.height=2;
                                                      document.getElementById('headers').style.top=2;">
whatever you have on top allo
</table></div>
      <script language="javascript">
document.write('<div ID="headers" style="height:20;left:0;width:100%;top:'
+document.getElementById('head').style.height+
';background-color:blue;position:fixed;">')
      </script>
table head
</div>
<br><br><br>
<table>
<script language="javascript">
for(i=0;i<70;i++)
document.write('<tr><td>line '+i);
</script>
</table>

then the simple solution for IE4 and above (as i understood from w3c site, overflow is available for divs from IE4)

<br><br><br>
<div ID="table" style="width:100%;height:100%;background-color:yellow;position:relative;overflow:scroll;">
<table>
<script language="javascript">
for(i=0;i<70;i++)
document.write('<tr><td>line '+i);
</script>
</table>
</div>

the <br>s stand for whaterver you want to be on top.

as to the title wich you could mask/unmask, the same issue applies but it does work in ie as well using frames and expression such as
<table height=\"100%\" align=\"center\" cellpadding=0 cellspacing=0 width=100%>
            <tr><td rowspan=\"2\" width=10%>
...
...
                  <td colspan=\"2\" onMouseOver=\"javascript:window.parent.document.body.rows='50,*';\"><a name=\"haut\">

in the top frame (title frame)

<a href=\"#haut\" onClick=\"window.parent.document.body.rows='2,*';\">masquer navig</a>

sorry about the '\'s everywhere but this code is part of a php page and the quotes had to be escaped
yups sorry i just posted seanpowells answer, apologies, i'll try to put it on lack of sleep
FAMING MESELF arghh !