Jaimon's Blog

Making Scrollable Tables with fixed headers

********** Please click here for an update script with additional functionalities like multiple header freezing, column freezing and multiple tables ***********

Although it is a common requirement, it’s not always straight forward to make scrollable tables with fixed headers. Here, we are going to try a few JavaScript solutions that could be suitable for most cases. I need to emphasize on that, because you might need to make a few tweaks to make it work in your environment, especially tables generated by web  frameworks.


To implement these JavaScript solutions, your tables should have an ID and width. Width can be a fixed value or a percentage. Since the width can be specified in percentage, it should also work when window get resized. It has been designed to introduce this functionality with minimal changes to your existing pages. So for the JavaScript functions to work, you only need to add the following lines to your HTML pages,

<script type="text/javascript" src="fxheader1.js"></script>
<script type="text/javascript">

Make sure you add the second JavaScript call after the table element. Replace dataTable with the ID of your table, and 300 with the height you require. Instead of specifying the height as a fixed value, there are ways to stretch the table to fill the page based on other components on the page. Last solution make use of such a method.

Browser compatibility

It’s been tested on the following browsers all running on Windows XP.

  • IE6
  • IE7
  • IE8
  • Firefox 2.0
  • Firefox 3.5
  • Google Chrome

The big table

Here is an example of a table we are going to introduce the scrolling functionality. Well, it is not really big, just big enough to test our functionality 🙂


Solution 1: Simple CSS only scrolling without fixing headers

With the help of a bit of CSS, we can implement a simple scroller. Enclose the table element within a div container with an overflow value of auto and a fixed height. Something like

<div style=’overflow:auto;height:300px;’>
<table …. />

You can see the demo at http://jaimonblog.appspot.com/datascroller/simpleScroller.html

Solution 2: Scrolling with fixed headers using table cloning

You can see a working demo at http://jaimonblog.appspot.com/datascroller/fixedHeaderFullClone.html

Download fxheader1.js and include it in your project as explained on the implementation section

How does it work?

  • First we put a scrollable div container around the table element as in our first solution.
    • create a div element
    • clone the table element using cloneNode(true)
    • added the cloned table to this div
    • replace the table element with this div
  • Create a container on top of the table to place the headers.
  • Attach scrollHeader function to the table container div’s onscroll event, so that we can align the heading when the table is scrolled horizontally.
  • We then clone the table and place it in the header container. Container height is set, so that only the header row is visible.
  • We then set a negative margin top on the original table to hide the actual header.
  • Attach fxheader function to window onresize event, so it works when window get resized.

Please note that, there are more than one way to do add a div element around our table element using JavaScript. You could speed up the process by adding these divs manually on the page as in Solution 1, because cloneNode function can be expensive. Make sure to use the correct IDs, so that rest of the code can find these. Please see the function addScrollerDivs in fxheader1.js for more details.

Solution 3: Scrolling with fixed headers using fast table cloning

You can see a working demo at  http://jaimonblog.appspot.com/datascroller/fixedHeaderFastClone.html

Download fxheader2.js and include it in your project as explained on the implementation section to get started.

Solution 2 will give you very accurate column widths at the expense of doing a full table cloning. If you have a table with lots of rows, this can take a while. If your rows have elements with unique IDs, you will have to change it on the cloned node to avoid  ID collision. Although it will work, it will lead to a sluggish user experience on pages with really large tables.

In solution 3, we are doing a fast clone without any child elements. Then we add the first row to it and set individual column width separately based on the offsetWidth property of each cell. You’ll have to offset cell margin/padding when setting the width. In our example, I deduct 3 from offsetWidth and that works fine for our table in all browsers I’ve tested.

Everything else is similar to solution 2.

Solution 4: Adding scrolling to table generated by ADF Faces 10g with fixed header (With and without pagination support) and automatic height stretching

Although in theory it is similar to solution 3, I had to make a few changes to make it work for a table generated by ADF Faces. The problem is ADF Faces creates three HTML tables for each af:table element. First and third tables are created for pagination support. It doesn’t create an ID for the actual data table itself, so we need to access it as a childNode of the container element. If pagination is there, we need to place this above our fixed header. Since we have the scrolling functionality, I thought the second pagination controls below the data table is not necessary, and I’m removing it from the page.

When cloning table data here, we have to update ID field of each element to avoid ID collision. We also have to set the correct selected index value for pagination selector combo box. Another functionality I’ve implemented here is the ability to auto stretch the table content to fit the page. You should pass in the ID of your last container component to make it work. Please see adjustHeight function in fxheader.js for more details.

As with the second and third solutions, you could add the following line to your JSPX page to get this working.

<afh:script source="fxheader.js" />
<afh:script text="fxheaderInit('testTable','footerContent');" partialTriggers="testTable" />


Where testTable is the ID of your af:table element and footerContent is the ID of your last container component for stretching. Partial Triggers are required here if used with pagination.

You can download a fully functioning JDeveloper project from http://jaimonblog.appspot.com/datascroller/ADF10gScroller.zip

Please note that it is created with  JDeveloper version If you are using 11g, then fixed header functionality is already part of it. (Although there are a few issues with it at the time of writing this. One such issue is discussed here http://forums.oracle.com/forums/message.jspa?messageID=4032492#4032492)

As I’m not able to provide a demo link, you can see some screen shots of this solution here,


With Pagination

Without Pagination

February 2, 2010 - Posted by | Uncategorized | , , , ,


  1. Great coding!

    Is there anyway I can toggle (show/hide) the scrollable (td?) area from the header (th?), and keep the header visible?


    Comment by Anon | February 9, 2010 | Reply

    • I’m assuming you’re using Solution 3. Yes, you can show/hide the scrollable area with a bit of Javascript.

      Something like ge$(‘dataTable:scroller’).style.display=’none’;
      and ge$(‘dataTable:scroller’).style.display=”;



      Comment by jaimonmathew | February 9, 2010 | Reply

  2. A really nice solution. Only problem I’m having, because of my lack of experience, is that I can not figure out how to control the column widths. Normally I do that with the width attribute for column groups. I can’t seem to get that to work in Solution 2. Can you help me out?



    Comment by Ken Lodding | February 15, 2010 | Reply

    • Hi Ken, if you can send me a sample html file, I can certainly have a look.
      BTW, I would suggest using Solution 3, if possible, as that is more efficient.


      Comment by jaimonmathew | February 16, 2010 | Reply

    • su vat chhe bhai

      Comment by dewd | March 11, 2015 | Reply

  3. Hi,

    First of all thanks for your solution. It works with simple adf-generated tables, but what if it will be more complex? I mean if there will be a header inside another header? I know javascript a little, so if you could help me, it would be great. How can i contact you?

    Comment by Eugene Kamenev | February 22, 2010 | Reply

    • Hi,

      If you can send a sample project file to mail @ jaimon dot co dot uk I’ll have a look..


      Comment by jaimonmathew | February 22, 2010 | Reply

  4. Information for everyone who is trying to make fixed header for adf-table:
    This script will not work at all if you forget to setup “width” attribute like this: , without this attribute, script causes error (tested on Firefox 3.5 linux version) on any kind of adf-table.

    But still cant get it right working for nested headers… I will send sample project to Jaimon, and then if we will find a solution I’ll post it here.

    Thanks Jaimon for your reply!
    Sorry for bad English, it is a foreign language for me 🙂


    Comment by Eugene Kamenev | February 22, 2010 | Reply

    • Hi Eugene, I’ve already mentioned that under Implementation section. You’ve to specify a width and ID at the least for the script to work, otherwise it will fail on *all* browsers. Again, as I’ve mentioned at the beginning of this post, this solution will *not* work for every case without making some tweaks to suite your individual needs. Use this as a guideline, rather than a finished product. Although having said that, in many projects, this *will* work without making any modification at all.


      Comment by jaimonmathew | February 22, 2010 | Reply

    • Hi Eugene, thanks for sending the sample project. In your case, you’ve two rows for header, so you’ll need to move two rows in to the outer div area. I’ve done a quick version, which you can download it from http://jaimon.co.uk/datascroller/fxheaderWithTwoRowHeader.js

      The only change is, now I’m using a for loop to add two rows in to tbody element, everything else remains the same. You may not even have to add the extra height, as the offsetHeight returns the combined height value.

      As this is a quick solution, I haven’t made any effort to make it as a generic solution, and I’ve only tested it on IE.

      One more thing about auto stretching in your page. You need to either declare your footer content just outside your panelPage or you need to compensate for the extra padding panelPage component adds.



      Comment by jaimonmathew | February 22, 2010 | Reply

      • Hi to all!

        Jaimon thank you very much! You script works good, i have made generic solution myself for any amount of header-rows. But you forgot about setting height of Scroller:fx:OuterDiv and margin-top for scroller 🙂 I have fixed it, and it works great. Thanks again!

        Comment by Eugene Kamenev | February 23, 2010 | Reply

  5. What if you also need a horizontal scroll? I’m kinda new in this web-design. But I have a table generated by a Access data base in asp script and seems to me that i cant use your solution because i have lots of colums which are set by the data.
    Any ideas?
    Thanks in advance.

    Comment by Fernando | February 25, 2010 | Reply

    • Hi,

      Horizontal scroll bar will come up automatically when the content can’t fit into the width specified. Open http://jaimon.co.uk/datascroller/fixedHeaderFastClone.html on your browser, then resize the browser with < 500 pixels in width, and you'll see horizontal scroll comes up. In the script I've also hooked on to scroll event, so your header will also get aligned as you scroll.



      Comment by jaimonmathew | February 26, 2010 | Reply

      • You convinced me, but I cant make it work. 😛
        How do I call the fxheder2.js in my asp page?

        I’m seeing the code of page you set as example and doing like this:
        Response.Write (“fxheaderInit(dataTable,300);”)
        Is it right?

        Comment by Fernando | February 26, 2010 | Reply

  6. Hi Fernando,

    If you’re using ASP.net, please see this page http://forums.asp.net/p/897239/970883.aspx for some solutions. You’ll also need to look at the table ID generated by ASP.net, and you’ll need to give that exact ID for the script to work.



    Comment by jaimonmathew | February 26, 2010 | Reply

    • I’m using ASP, not ASP.net, too complex for me for now, maybe later i’ll do in ASP.net. 😀

      Comment by Fernando | February 26, 2010 | Reply

  7. I managed to freeze the header! Using the fxheader2.js.
    But now I realized that i need to freeze the first two rows, but i wasnt able to to it with the fxheaderWithTwoRowHeader.js.
    Any Idea?
    Gonna keep trying.
    You already helped a lot!

    Comment by Fernando | February 26, 2010 | Reply

    • Hi Fernando,

      Good to hear you’re making progress. fxheaderWithTwoRowHeader.js file was for a specific requirement, and shouldn’t be used as a general library. If you want to make first two rows freeze, then you should add two rows as done in fxheaderWithTwoRowHeader.js. But you should also adjust the height of OuterDiv and negative top margin to include two row’s height.


      Comment by jaimonmathew | February 26, 2010 | Reply

      • Hi Jaimon,

        I’m trying to adjust using the fxheader2.js (is that right?); But, i’m not beeing able to find where to adjust correctly the height. Any tips?


        Comment by Fernando | February 26, 2010 | Reply

  8. Hi Fernando,

    Since it seems a general requirement, I’ve made another page to add this functionality. Please check http://jaimon.co.uk/datascroller/fxHeaderMultipleRowFreezing.html and http://jaimon.co.uk/datascroller/fxheader3.js for more details. You can now pass in a parameter to fxHeaderInit function saying how many rows should be freezed.



    Comment by jaimonmathew | February 27, 2010 | Reply

    • Hi Jaimon,

      Thanks for everything, you helped me a lot, gonna try to understang better what the fxheader is doing.

      Thanks again,


      Comment by Fernando | February 28, 2010 | Reply

    • Jaimon,

      When you say I have to pass in a parameter do fxHeaderInit, means that I have to substitute the _noOfRows parameter by the number of rows it should be freezed or I need to pass another parameter with the number of rows I want freezed?

      this.fxheaderInit = function(_tid,_sheight,2)
      this.fxheaderInit = function(_tid,_sheight,_noOfRows,2)

      Problably neither way, because I aint beeing able to make it work.
      Sorry to keep bothering you.

      Thanks again,


      Comment by Fernando | March 1, 2010 | Reply

      • Hi Fernando,

        you shouldn’t be making changes to fxheader3.js at all. Change the number of rows where you’ll be *calling* fxHeaderInit method, ie in your HTML page.



        Comment by jaimonmathew | March 1, 2010 | Reply

      • Jaimon,

        I make it work, but i’m not sure if this is the right way. This is what i made:
        this.fxheaderInit = function(_tid,_sheight,_noOfRows) {


        Comment by Fernando | March 1, 2010 | Reply

  9. […] point to get Vimeo integrated, I haven’t isolated the code as I’ve done in my other blogs here and here. See it in action For a live demo, please click here. Download code You can […]

    Pingback by Managing Vimeo video player via Javascript using Moogaloop API « Jaimon's Blog | March 2, 2010 | Reply

  10. Hello,

    I found your script wonderful!

    But I have an issue, the fields of my table contains checkboxes, combo boxes, textfields, etc..

    So someone can update batch style data.

    But for some reason the header is freeze ok, but I lost my real data on the fields.

    Do you have some idea?


    Comment by Blanca Esqueda | March 4, 2010 | Reply

    • Hi,

      Which solution are you using? Does your header contains any of these fields?
      One thing to keep in mind is to avoid ID duplication as explained in my ADF faces sample, which contains a changeIds method to replace ID values.


      Comment by Jaimon Mathew | March 4, 2010 | Reply

  11. Thanks for the script! It’s working great on most of my tables. However, I have run into an issue with multiple tables on the same page. I am using solution 3 with the fxheader3.js file.

    When I try to make more than one table scrollable on the same page, the header for the second table appears where the header should be for the first table. So…the first table has the header from the second table, and the second table has no header, just the ‘Please wait while loading the table…’ message. Any ideas?

    Comment by Dan | March 10, 2010 | Reply

    • Hi Dan,

      Its not actually desinged for multiple tables, as I’ve hard coded the IDs for some of the elements I create via DOM. They are all named with ‘Scroller:’ prefix. The only thing I can suggest is to create an array to store table id, rather than storing it in tid. Then prefix all temporary elements with the table id instead of ‘Scroller:’.



      Comment by Jaimon Mathew | March 10, 2010 | Reply

      • Thanks again! That did the trick. I just added tid in front of ‘Scroller:’ so it’s now tid+’:Scroller:’ and now it works.

        I call the fxheaderInit() for each table, so I don’t need to use an array. Most of the time I only have one table, so I’m not worried about calling the function a bunch of times.

        Comment by Dan | March 10, 2010 | Reply

    • Hi Dan

      Please check the new post at https://jaimonmathew.wordpress.com/2010/03/19/making-scrollable-tables-with-fixed-headers-updated-2/ including multiple tables on the same page



      Comment by Jaimon Mathew | March 19, 2010 | Reply

  12. Dear Jaimon,
    It is great script you have written for fixed header.
    I searched on google a lot for fixed header table but every time I found browser compatibility issue for other scripts.
    Yours one is great one.
    I have a small question. Can we also freeze a number column of the table? If this can be done then it will be most flexible script for managing large data tables.


    Comment by Manohar | March 18, 2010 | Reply

  13. Jaimon
    Any ideas how I could get javascript sorting to work with this? I have a script that sorts by clicking on thead using appendChild to move the rows in the table. It’s not working with this and am trying to figure out how to do it.

    It’s a good script though, thank you

    Comment by Nix | March 19, 2010 | Reply

    • Hi Nicky,

      This script does modify the DOM, and also hide the original thead. So any script depends on the original DOM will not work with this. If it is your own script, you could modify it to work with the new DOM structure. Please use a tool like Firebug, IE8’s Developer tool etc to see the new structure.



      Comment by Jaimon Mathew | March 19, 2010 | Reply

  14. Hello,

    what kind of licence do you use for fxheader2.js.
    I would like to use it in my work (commercial website), but I need to make sure that licence is OK.
    What about modifications of this script?


    Comment by kris | April 6, 2010 | Reply

    • Hi Kris,

      As I haven’t explicitly mentioned any licenses in my post, there is no restriction on the use of my script. The usual “no responsibility” policy do apply, to save my back. It would only be fair to keep the author line on the script file, or some mention of it.

      BTW, have you had a look at the updated script?


      Comment by Jaimon Mathew | April 6, 2010 | Reply

  15. Hi
    I have a table definition that looks like this:



    When i attempt create a fixed header with:
    It returns:
    Line: 126
    Error: ‘offsetHeight’ is null or not an object
    It works ok if i only use 1 header row. But i need to make the both fixed.
    I hope you can help me.

    Comment by DR_CHAOS | May 4, 2010 | Reply

    • Hi,

      Have you tried it with the updated script? If it still doesn’t work, send me an email with the very minimum code to reproduce the error (mail at jaimon.co.uk)


      Comment by Jaimon Mathew | May 4, 2010 | Reply

      • Hi
        I have sent you an email hat reproduces the error.

        Comment by DR_CHAOS | May 5, 2010 | Reply

        • Hi Nicolai,

          On line 126 of fxHeader_0.1.js, add a sanity check to get rid of the error, like

          if(oc[j]) tHeight+=oc[j].offsetHeight;

          Let me know if it works, so I can update my version on the blog.



          Comment by Jaimon Mathew | May 5, 2010 | Reply

  16. Hello Jaimon,
    working on a site that has two iframes that scroll up and down. By selecting the items in the ‘display’ frame you insert a row into ‘register’ frame bellow. The ‘register’ frame bellow ‘display’ only shows two rows. One the fixed ‘header’. The other row[0] as all inserted rows are inserted at [0] index. I had it working fine with the CSS heights written in pixels but when I changed height to % percentages the fixed ‘header’ covers the row[0] while only ocupying half the ‘register’ window. I can only see
    row[1], row[0] is covered by the fixed ‘header’. I did not use any cloneing to achieve this with pixel heights in the CSS.
    ‘register’ iframe contains ‘checkout.html’ with these divs
    1.content(contains all)
    2.welcome(inside content outside others)
    3.checkoutcontainer(under welcome contains tablecontainer)
    4.tablecontainer(contains form around table and other divs)
    The ‘tablecontainer’ height is set at 98% while the tables height is not set. it only has a width of 100%.
    I’ve never cloned a header to fix it’s position. the ‘header’ position isrelative top 0% left0% and once the ‘welcome’ div display style is set to none tbody style posTop should get the table to drop but it dosen’t and
    row[0] is still covered by the fixed ‘header’. Any help would be great. (sorry about the length of this comment).

    Comment by Heinz | May 22, 2010 | Reply

    • Hi Heinz,

      Is this related to my article? Either way, I wouldn’t recommend using percentage for table or row heights. You’ll need to use absolute values..


      Comment by Jaimon Mathew | May 24, 2010 | Reply

  17. Fang Thanks again. You are right. The problem has to do with the HTML document itself. The generated row contains 9 cells as written in the JS. Unfortunatley the first cell .code dosen’t follow the CSS rule width of 10%, instead appearing as 25%+ and sibling cells appear to follow the CSS rules while the row .itemrow itself dose span 100% of the table, the other rows vary in width according to the amount of td/th tags they hold. This means that the document HTML div tags CSS positioning rules are wrong.

    I figured this out by setting the back-ground color of .tablecontainer to ‘grey’ and was amazed that no grey appeared on screen. Then I set .tablecontainer height to 100% and could see that the .tablecontainer 100% width was only 25%+ matching .code width.

    CSS rules are strict and only as good as the HTML they support.

    Remembering that the HTML was working fine untill I decided to automate ‘Scaleing’ of elements by changing height values from pixels to percentages I now have to go back through all the CSS rules for each element and change them back to pixel units

    Most browsers claim to support height:% values for most elements and apparently the table elements Siblings fall short of these claims and maybe the cause for utilizing nested div tags with display:table-cell; and display:table-row; CSS rules.

    ‘Don’t fix it if it is not broken’ sounds reasonable but saving your file as a different named file when closing the file is appropriate when trying to upgrade site ability from fixed/absolute units to relevant/scaleable units.

    I never ‘cloned’ the thead to change it’s relative position to fixed which seems to be the popular method in use today. Nor did I change the thead className as I would then had to change the className of each and every td in the thead itself in order not to break the thead CSS rules. Instead I set the tr in the thead by CSS rules to

    #header { position:relative; left:0px; top:16px; width:95.5% }

    /*width set to overide tendancy for the row to surpass the containing div .tablecontainer and top set not to cover rows[0] when the header psition was changed from relative to fixed*/ and then called document getElementById(‘header’) style position = ‘fixed’ in the external JS file which worked fine untill I changed the measurment units in the CSS from pixels to percentage.

    It is not the end of the Iframe that is necessary as it provides for simple cleaner HTML file TEMPLATES to be added to a page easily without the massive asp style HTML pages that scroll on forever. It probably is the end of the table element as we know it. With new CSS rules, display:table-row; and display:table-cell; the latter I consider redundant.

    Consider this:


    function insertItemRow(button){
    var fs=button.parentNode.parentNode;
    var q=fs.getElementsByTagName(‘select’)[2].value;
    if(q!=” || q!=0) {
    var code = fs.getElementsByTagName(‘input’)[0].value;
    var item = fs.getElementsByTagName(‘input’)[1].value;
    var color = fs.getElementsByTagName(‘select’)[0].value;
    var size = fs.getElementsByTagName(‘select’)[1].value;
    var price = fs.getElementsByTagName(‘input’)[2].value;
    var quantity = fs.getElementsByTagName(‘select’)[2].value;
    var val = [[quantity],[price]];
    var multiply = 0;
    multiply+= (val[0]*val[1]);

    var subtotal = top.frames[‘register’].document.getElementById(‘subtotal’);
    var tablecontainer=document.getElementById(‘tablecontainer’);

    var header=document.getElementById(‘header’);

    var itemrow=document.createElement(div);
    itemrow.setAttribute(‘title’,’Item that you have ordered.’);

    var p=document.createElement(p);


    var addcode=document.createElement(span);




    //one span added to p added to itemrow added to tablecontainer


    // in my situation insertrows[0]


    I’m already months late but would consider the createElement(div) change from the insertrow and HTML table if it gauranteed scalability of the index page on load to the client monitor or screen. The Iframe positions, heights and widths are all relative units or percentages as well as the index page divs, it’s only the table rows that have to be absolute/fixed units of height to change header position from relative to fixed. It has been popular to use clientheight and width scripts to adjust for the client screen or monitor size and this bulks up the external JS files with repetitive calls to clientHieght functions etc.

    Given the introduction of new CSS rules display:table-row; which according to published standards causes the element to render like a table row, even though display:block; should work fine in my example.

    it looks like the table element may be a thing of the past as far as webpages are concerned but the Iframe should be a protected element as it provides for the simplest addition of HTML templates and video feed technologies. I would guess that Iphone and Ipad followed by others have already used this to generate thier collective fortunes by iradicating the troublesome table element.

    Sorry again about the length of this thread. Any directional advice would be greatly apprieciated.

    I will foreward this to Jaimons Blog as Jaimon currently is the master of the ‘cloneNode’ and fixed header in table element script, though he readily admits that the table rows are not scalable to client monitor/screen resolution as thier unit heights are fixed/absolute. I’d like his feed back on the new CSS rules and what he thinks the future holds for the table and Iframe elements.

    Comment by Heinz | May 26, 2010 | Reply

  18. Hi Jaimon,
    Hope doing well,
    I have used fxHeader_0.2.js file, Its really helped me a lot for fixing Grid header. I am able to fix the grid header with vertical & horizontal scroll’s as per my requirement.
    But now I am facing two issues.

    – CB – State_ID – Analysis – –
    – – – Date – –
    – CB – Some Text Crossing – 01/06/2010 12:00:00 – –
    – CB – Some Text Crossing – 01/06/2010 12:00:00 – –
    – CB – Some Text Crossing – 01/06/2010 12:00:00 – –
    – CB – Some Text Crossing – 01/06/2010 12:00:00 – –

    In above table structure you can see, header is having one check box (CB) for select all action, State_ID column and Analysis Date.

    1. header cell(td) width is not adjusting to row->td cell with automatically.
    I mean If i do nowrap on tr->td cell contents what ever the length TD cell arrages as single line text for that lengt that TD’s header cell right border also should come
    You can see For State_ID header content is ‘Some Text Crossing’
    2. the other issue By clicking on Select All Check box(CB) on header row, I am calling a JS function for onclick event, in which I am trying to get header checkbox object(CB)’s value(checked/unchecked,i.e true/false), but always object is coming as null.
    In two ways I tried,
    Header Checkbox ID is ‘selAll’ in table

    var isChecked = document.forms[‘actionForm’].elements[‘selAll’];


    var isChecked = document.getElementById(“selAll”);

    Code for getting all row’s check boxes and checking/unchecking.

    My problem is after I am unable to get the Header checkbox object, Please could you tell me the way how to handle it.

    finally One more issue was, I want to fix the first column(Check box (CB)) of table, As this is a very big table with horizontal & vertical scrolls, user can navigate to right most side of the row, As we will fix the checkbox column, So at any time user can check any record.

    But even though I have passed no of column parameter(1) to your js function, i.e
    Its not handling properly.
    So I am getting the checkbox column as seperately in one block, down to that remaining table is getting placed, I want this along with the table with proper alignments..

    Please could you helpme out in this…


    I tried in both the ways

    Comment by Gopal | June 1, 2010 | Reply

  19. Hi Jaimon,

    It is great script you have written for fixed header.

    I am using fxheader2.js file, on onClick function my table div width will increase, so the same time I need increase table width also. Now the table data section width is increasing, but header part is not increasing, its fixed. So dynamicaly I need to increase the table width???

    Comment by Sreejesh | June 17, 2010 | Reply

  20. Hi !

    Thank you very much for your script ! I work with very long table and you save my life. 😉
    Your idea to clone the table is very smart.

    On my web page, i would like to use anchor to reach specified lines in the table. But the classical link doesn’t work : its bring me to the good line… but on the fixed div ! !
    Is there a trick to use anchor in the scroll div ?

    Thanks for help, and many many thanks for your great work 🙂

    Comment by Fred | December 7, 2010 | Reply

  21. Hi Jaimon,

    Although I didn’t use your solutions exactly as shown I did take some of the ideas from “Solution 3” and used them on my web page. In particular I hardcoded the DIVs and table headers to avoid the cloning completely. By making these DISPLAY:NONE in the CSS I can still have the table do basic scrolling if JavaScript is turned off.

    I also added a footer and sorting/filtering to the table.

    Feel free to have a look here:


    Thanks for the info!

    Comment by Graham | February 10, 2011 | Reply

  22. […] By jquery_riser on August 30th, 2011 I require a similar jQuery or Javascript Solution like http://fixedheadertable.com/livedemos or https://jaimonmathew.wordpress.com/2010/02/02/scroller. […]

    Pingback by Require HTML Table Header and Column Fixer jQuery or Javascript? « Jquery « Jquery Platforms | August 30, 2011 | Reply

  23. Hi Jeamon!

    It’s a great script! But there is an option to unload and init or reload this script?
    I have a CakePHP table component, and i am loading another tables in this CakePHP table cells with prototype ajax uploader.
    The first load is fine, but the others are bad.

    Here is my code:

    if (datatype == ‘clearbox’){
    var ajax = new Ajax.Updater(div, url, {method: ‘get’,onComplete: function (request){CB_Init()},onFailure: function(response) {alert(response);},onException: function(request,error) {alert(error.message);}});}
    else if (datatype == ‘gmap’){
    var ajax = new Ajax.Updater(div, url, {method: ‘get’,onComplete: function (request){GUnload(); initMap()},onFailure: function(response) {alert(response);},onException: function(request,error) {alert(error.message);}});}
    else if (datatype == ‘fxheader’){
    var ajax = new Ajax.Updater(div, url, {method: ‘get’,onComplete: function (request){fxheaderInit(‘exampletable’,400,2,0); fxheader();},onFailure: function(response) {alert(response);},onException: function(request,error) {alert(error.message);}});}

    As You can see there is an GUnload() function for Google Maps, but i didn’t find similar in your script.

    Have You any idea?

    Thank You:


    Comment by Zsolt Kecskés | October 28, 2011 | Reply

    • Hi Zsolt,

      You could try the following,

      First, edit the fxHeader script to include a new function to reset the internal tableArray used. (Something like this.resetTbl = function() {tbl=[];} right after the line var tbl=new Array();)
      Then call this before calling fxHeaderInit method. Let’s see if that works..



      Comment by Jaimon Mathew | October 28, 2011 | Reply

  24. Hi Jaimon,
    This is fantastic and will be very helpful for some retrofitting I’m working on. (Your solution 3 works best for me.) My application has the table in an iframe. (It’s the last thing on the page.) My main page sets the height of the iframe to whatever space is left below on the page. Then I set the length of the table equal to the iframe height (minus a bit). This renders the table such that the main page doesn’t produce a vertical scroll bar but only one on the table, if needed. My next challenge is to make the table resize as necessary as the main page is resized. I am able to dynamically resize the iframe but my javascript chops are not good enough to figure out how resize the table as needed. I see that fxheader() is called on resize but I couldn’t figure it out. (I tried running fxheaderInit with the new size but nothing changed.) Thanks again and thanks in advance for any help for any help.

    Comment by Steve | November 4, 2011 | Reply

    • Hi Steve,

      If you send me a small reproducible test file, I can certainly take a look.



      Comment by Jaimon Mathew | November 4, 2011 | Reply

  25. Sent! Thanks.

    Comment by Steve | November 7, 2011 | Reply

  26. Jaimon,

    THANKS! From my testing so far it works perfectly. My use case, in essence, answers questions and then produces the results in a table to fill the remaining space on the page. On the off chance that the user resizes the window this now smoothly adjusts. Thanks so much.


    Comment by Steve | November 9, 2011 | Reply

  27. It does have one peculiar behaviour. As it renders the table it is full width (as desired) but then the last thing it does is “pull in” (On short tables this looks instantaneous) Then if you re-size the window it jumps to its proper size. Another (minor) thing that I notice is that for short tables that don’t need a scroll bar it would be nice to use the complete width and let it pull in only when needed. (I have 20+ columns in my use case so every pixel counts.) But nonetheless Jamon this wonderful as is.

    Comment by Steve | November 12, 2011 | Reply

  28. Hi Jaimon,

    Great work !

    I’m using your solution in my application just extended a bit.

    I’m using ajax to load the table. So just added a refresh function there and calling the plugin after loading the data. I’m giving the code here you may add it in your post.

    Just I’m adding the following function at the end of your codes.

    this.fxheaderRefresh = function (_tid) {
    tid = _tid;
    var olddiv = document.getElementById(‘Scroller:fx:OuterDiv’);
    if(olddiv) {
    var needRemoved = document.getElementById(_tid).parentNode;

    And Calling the function like follows:

    ajax success function (
    fxheaderRefresh(‘myTable’); //refresh the fixheader

    //load the content

    fxheaderInit(‘myTable’, 355); //init the fixheader for the table

    Thank you again for your good work !

    Comment by Rashedul Islam Sumon | April 6, 2012 | Reply

  29. Hi Jaimon,

    unable to download fxheader3.js… can you please reupload ???


    Comment by Henry | May 3, 2012 | Reply

  30. hi jaimon am new in JS , and i try the solution2 unsuccessfully, can somebody help me with some code or examples ?? i have these errors

    Uncaught TypeError: Cannot read property ‘width’ of null fxheader2.js:24
    addScrollerDivs fxheader2.js:24
    fxheaderInit fxheader2.js:84
    (anonymous function)

    Comment by ullysh | July 6, 2012 | Reply

  31. Hi Jaimon.

    I am using your solution no 2 and it works perfectly fine. The tables are generated by WebSphere Portlet Factory. Also I have a tooltip on one of the cells on the table. Because the script overlaps one table above the other, the tooltip is not working as expected. Do you suggest any trials for me to overcome this issue?

    Thank you

    Comment by Muralidhar Chavan | December 4, 2012 | Reply

  32. Hi Jaimon. Please ignore my earlier comment. Using solution 3 resolved the issue. Thank you very much.

    Comment by Muralidhar Chavan | December 4, 2012 | Reply

  33. Thanks for provding simple and nice various solutions.

    Comment by Murali | April 3, 2013 | Reply

  34. I was searching for a stuff like this. I got it. Thanks a lot.

    Comment by selvin thangadurai | June 18, 2013 | Reply

  35. How do you print all data within the scrollable area?

    Comment by Les | September 4, 2013 | Reply

  36. how do you print all data with in the scrollable table?

    Comment by leslie | September 4, 2013 | Reply

  37. awesome, just awesome, I was searching this feature for more than one week and was stuck.
    Thank you for this, it helped me a lot

    Comment by Subh Dey | January 29, 2014 | Reply

  38. What is ADF?

    Comment by Arun Jayapal | April 10, 2014 | Reply

  39. On Submit of the form…I am getting Comma Seperated values bcoz of table clone…What is the solution
    formcollection frm
    frm[“name”] = ‘DAV,DAV’

    Comment by David nadar | October 16, 2014 | Reply

  40. […] Making Scrollable Tables with fixed headers « Jaimon’s Blog – Feb 02, 2010 · Making Scrollable Tables with fixed headers ***** Please click here for an update script with additional functionalities like multiple header freezing …… […]

    Pingback by Fix Bad Pool Header Chrome Errors - Windows XP, Vista & Windows 7, 8 | October 28, 2014 | Reply

  41. […] Making Scrollable Tables with fixed headers « Jaimon’s Blog – Feb 02, 2010 · Making Scrollable Tables with fixed headers ***** Please click here for an update script with additional functionalities like multiple header freezing …… […]

    Pingback by Fix Bad Pool Header Java Errors - Windows XP, Vista & Windows 7, 8 | November 6, 2014 | Reply

  42. I am using fxheader2. I need to scroll the table to make a certain cell visible. I can get hod of the dataTable with cell.parentNode.parentNode.parentNode. If I go 1 step further I get my own surrounding div and not the dataTable:scroller. How can I get hold on that?

    Comment by Birthe Berland | March 12, 2015 | Reply

    • Is Mr. Mathew still responding to this blog? I’ve seen data html tables and pages that the scrollbars disappear on when the row numbers are minimal and appear as new data is loaded in real time (or as close as the web can get). It’s amazing that so many sites are running without using this scripting technique and I’m wondering if android scripting has a similar script for touch screen technology etc. Also, if device or screen size and resolution are tested by script on the first call to any site then specific tables can be run on any particular device or screen size. Also, I believe that short of script comments that the actual script variables should not be shortened to disambiguate the script procedure even more. Mr. Mathew might add a few more comments to the script itself in order that us laymen have a better understanding of what the script is doing at every step of the script. Best regards, Heinz.

      Comment by Heinz Stapff | April 27, 2015 | Reply

  43. I used your original code example for Making Scrollable Headers with Fixed Headers on a table I am working on. Your example file scrolls vertically, which is what I wanted. My attempt to use it scrolls horizontally. I am not that good of a programmer, and couldn’t figure out what to change. Can I force it to scroll vertically? Can it scroll vertically and horizontally at same time?

    When I used my table before trying the scrolling, it automatically fix my screen width. The scrolling attempt doesn’t do this, so you need the horizontal scrolling. If I can only to vertical, I need it to go back to putting all columns on one screen.

    Comment by Jim Humphrey | April 24, 2015 | Reply

    • 39.I used your original code example for Making Scrollable Headers with Fixed Headers on a table I am working on. Your example file scrolls vertically, which is what I wanted. My attempt to use it scrolls horizontally. I am not that good of a programmer, and couldn’t figure out what to change. Can I force it to scroll vertically? Can it scroll vertically and horizontally at same time?

      When I used my table before trying the scrolling, it automatically fix my screen width. The scrolling attempt doesn’t do this, so you need the horizontal scrolling. If I can only to vertical, I need it to go back to putting all columns on one screen.

      Comment by Heinz Stapff | April 27, 2015 | Reply

  44. Hi Jaimon.. none of the link are working on this page..I’ve a scrollable table with fixed header which works in IE8 but doesn’t in Chrome..

    trs[x].style.setExpression(“top”, “this.parentElement.parentElement.parentElement.scrollTop + ‘px'”);
    doesn’t work in Chrome.

    this.parentElement.parentElement.parentElement is coming undefined. Please help.

    Comment by Pras_mus | July 12, 2015 | Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: