tags:

views:

8043

answers:

6

I would like to be able to "tweak" an HTML table's presentation to add a single feature: when scrolling down through the page so that the table is on the screen but the header rows are off-screen, I would like the headers to remain visible at the top of the viewing area.

This would be conceptually like the "freeze panes" feature in Excel. However, an HTML page might contain several tables in it and I only would want it to happen for the table that is currently in-view, only while it is in-view.

Note: I've seen one solution where the table data area is made scrollable while the headers do not scroll. That's not the solution I'm looking for.

+2  A: 

This is not a "tweak" - it's a request that is far beyond the limitations of html and css. I would suggest that you go back and concentrate on your core requirements, in the hope that you might conceive of a more straightforward way to achieve them. If, after this deliberation, you're still not willing to compromise on this feature, then be prepared to invest in a non-trivial javascript solution.

ozan
Ah-- I meant a "tweak" from a user experience point of view, not an implementation point of view. I.e. I don't want a solution that radically changes the presentation of my tables, I want them to be pretty much standard-looking tables on a page, except to just add a header row that sticks at the top of the view while scrolling down through the table.
Craig McQueen
Hmm that sounds wise. Unfortunately I'm stubborn :-) and I think what I'm wishing for would be great for the user experience if it can be achieved. I'll probably end up trying a JavaScript solution. If it succeeds, hopefully it should be useful to others. But I wouldn't be surprised if I can only get it working for some browsers.
Craig McQueen
I agree that it'd be great for the user experience, particularly if there's no alternative way to display the data (through pagination for instance). If you're concerned about cross-browser compatibility, you might make it somewhat easier for yourself by using jQuery or prototype as a starting point. Also if you work on it a bit and post your code somewhere, I -- and I'm sure others here -- could help you out with it.
ozan
Thanks for the advice. See my answer with a jQuery based solution.
Craig McQueen
A: 

If you use a full screen table you are maybe interested in setting th to display:fixed; and top:0; or try a very similar approach via css.

Update

Just quickly build up a working solution with iframes (html4.0). This example IS NOT standard conform, however you will easily be able to fix it:

outer.html

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;   
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">     
    <head>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     <title>Outer</title>
  <body>
    <iframe src="test.html" width="200" height="100"></iframe>
    </body>
</html>

test.html

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;   
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">     
    <head>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     <title>Floating</title>
    <style type="text/css">
      .content{
        position:relative; 
      }

      thead{
        background-color:red;
        position:fixed; 
        top:0;
      }
    </style>
  <body>
    <div class="content">      
      <table>
        <thead>
          <tr class="top"><td>Title</td></tr>
        </head>
        <tbody>
          <tr><td>a</td></tr>
          <tr><td>b</td></tr>
          <tr><td>c</td></tr>
          <tr><td>d</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
        </tbody>
      </table>
    </div>
    </body>
</html>
merkuro
Won't work for multiple tables like the asker requests
a_m0d
@a_m0d, true...but the request sounds a big confusing. Either we are missunderstanding it, or the asker doesn't completely understand what he wants.
Jonathan Sampson
Here is another solution using some javascript http://www.imaputz.com/cssStuff/bigFourVersion.html
merkuro
+3  A: 

Using display: fixed on the thead section should work, but for it only work on the current table in view, you will need the help of JavaScript. And it will be tricky because it will need to figure out scrolling places and location of elements relative to the viewport, which is one of the prime areas of browser incompatibility.

Have a look at the popular JavaScript frameworks (jQuery, MooTools, YUI, etc etc.) to see if they can either do what you want or make it easier to do what you want.

staticsan
Thanks for the advice. I did make a solution using jQuery—see my answer.
Craig McQueen
A: 

I've encountered this problem very recently. Unfortunately, I had to do 2 tables, one for the header and one for the body. It's probably not the best approach ever but here goes:

<html>
<head>
<title>oh hai</title>
</head>
<body>
<table id="tableHeader">
  <tr>
    <th style="width:100px; background-color:#CCCCCC">col header</th>
    <th style="width:100px; background-color:#CCCCCC">col header</th>
  </tr>
</table>
<div style="height:50px; overflow:auto; width:250px">
  <table>
    <tr>
      <td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
      <td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
    </tr>
    <tr>
      <td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
      <td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
    </tr>
  </table>
</div>
</body>
</html>

This worked for me, it's probably not the elegant way but it does work. I'll investigate so see if I can do something better, but it allows for multiple tables.

Go read on the overflow propriety to see if it fits your need

Gab Royer
Hmm not working, i'll try to fix this, but the approach remains, you have to use the overflow:auto proprety
Gab Royer
it is working now sorry!
Gab Royer
I appreciate your solution and its simplicity, however in my question I said "Note: I've seen one solution where the table data area is made scrollable while the headers do not scroll. That's not the solution I'm looking for."
Craig McQueen
+11  A: 

I've made a proof-of-concept solution using jQuery.

View sample here.

I've now got this code in a Mercurial bitbucket repository. The main file is tables.html.

Update: I'm aware of one issue with this: if the table contains anchors, and if you open the URL with the specified anchor in a browser, when the page loads, the row with the anchor will probably be obscured by the floating header.

Update 2: I've improved it recently after some feedback via bitbucket, but it seems to not be displaying so well in Chrome. Hopefully I can fix that soon.

Craig McQueen
Dude that is seriously SWEET
James McCormack
+1  A: 

Possible alternatives

js-floating-table-headers

js-floating-table-headers (Google Code)

In Drupal

I have a Drupal 6 site. I was on the admin "modules" page, and noticed the tables had this exact feature!

Looking at the code, it seems to be implemented by a file called tableheader.js. It applies the feature on all tables with the class sticky-enabled.

For a Drupal site, I'd like to be able to make use of that tableheader.js module as-is for user content. tableheader.js doesn't seem to be present on user content pages in Drupal. I posted a forum message to ask how to modify the Drupal theme so it's available. According to a response, tableheader.js can be added to a Drupal theme using drupal_add_js() in the theme's template.php as follows:

drupal_add_js('misc/tableheader.js', 'core');
Craig McQueen