简体   繁体   中英

Fixed html table header while scrolling

I have the following table structure:

<table>   
<thead>   
    <tr>   
        <th colspan="4">Current</th>   
        <th colspan="4">New/Requested</th>   
    </tr>   
    <tr>   
        <th nowrap="nowrap">RSD &nbsp;&nbsp;&nbsp;&nbsp;</th>  
        <th nowrap="nowrap">CRSD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
        <th nowrap="nowrap">MSD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
        <th nowrap="nowrap">Open QTY &nbsp;&nbsp;&nbsp;&nbsp;</th>   
        <th nowrap="nowrap">CRD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
        <th nowrap="nowrap">CRSD &nbsp;&nbsp;&nbsp;&nbsp;</th>  
        <th nowrap="nowrap">MSD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
        <th nowrap="nowrap">Open QTY &nbsp;&nbsp;&nbsp;&nbsp;</th>   
        <th nowrap="nowrap">Action</th>   
        <th nowrap="nowrap">Reason</th>   
        <th nowrap="nowrap">Action Code Status </th>   
    </tr> 
    <tbody>
        <tr>
            <td></td>  
            <td></td>   
            .....plenty of rows
        </tr>
    </tbody>
</thead>   
</table> 

I am trying to fix the header so that if I scroll down it stays visible. I looked at this post but couldn't understand it. How can I do this?

I have written the following code in order to achieve my goal (as asked in question)-

Here is the plugin i have written.

(function ($) {
   $.fn.scrollbarTable = function (i) {
       var o = {};
       if (typeof (i) == 'number') o.height = i;
       else if (typeof (i) == 'object') o = i;
       else if (typeof (i) == 'undefined') o = {
           height: 300
       }
       return this.each(function () {
           var $t = $(this);
           var w = $t.width();
           $t.width(w - function (width) {
               var parent, child;
               if (width === undefined) {
                   parent = $('<div style="width:50px;height:50px;overflow:auto"><div style="height:50px;"></div></div>').appendTo('body');
                   child = parent.children();
                   width = child.innerWidth() - child.height(99).innerWidth();
                   parent.remove();
               }
               return width;
           }());
           var cols = [];
           var tableCols = [];
           $t.find('thead th,thead td').each(function () {
               cols.push($(this).width());
           });
           $t.find('tr:eq(1) th,thead td').each(function () {
               tableCols.push($(this).width());
           });
           var $firstRow = $t.clone();
           $firstRow.find('tbody').remove();
           $t.find('thead').remove();
           $t.before($firstRow);
           $firstRow.find('thead th,thead td').each(function (i) {
               $(this).attr('width', cols[i]);
           });
           $t.find('tr:first th,tr:first td').each(function (i) {
               $(this).attr('width', tableCols[i]);
           });
           var $wrap = $('<div>');
           $wrap.css({
               width: w,
               height: o.height,
               overflow: 'auto'
           });
           $t.wrap($wrap);
       })
   };
}(jQuery));

How to use:

$(document).ready(function(){
    $('table#tabss').scrollbarTable();
}

hope it will help someone somewhere..

Any way thanks to all of you for your kind support... :)

I know that I'm late to the party, but the jQuery Fixed Table Header Plugin by Mustafa OZCAN is fantastic. Just include it, as well as jQuery itself, and set it to work on your table like so:

<script type="text/javascript"> 
$(document).ready(function() { 
   $('#YourTable').fixedtableheader(); 
}); 
</script>

Replace #YourTable with the ID of your HTML table, and the plugin does the rest.

Alas, how I envy people who get to use jQuery. I created a pure javascript and CSS solution for those who are prevented by application limitations from loading a library.

Basically, CSS positions the table and table header row, and tricks the table into behaving like divs. Then javascript manipulates the CSS positioning of the table header row and a "mask" div that hides the moving rows as the table scrolls up (an improvement would be to modify the javascript to detect collision and hide rows that scroll up past the header).

The weakness of this approach is that you now have to set the widths for all the columns.

The relevant components are:

<!-- divs with IDs are manipulated with javascript -->
<div class="fixedTableHolder">

  <div class="maskHolder">
     <div id="mask" class="mask">&nbsp;</mask>
  </div>

  <div class="fixedTable">
    <div id="theTable" class="theTable">

       <!-- here is the table, header row must have an ID -->
       <table border="0" cellspacing="5" cellpadding="5"> 
          <tr id="thFixed" class="thFixed"> 
            <td class="col1">Header cell 1</td> 
          </tr>
          <tr>
            <td class="col1">regular cell</td>
          </tr>
       </table>
    </div>
  </div>
</div>

Here is a demo in jsFiddle: http://jsfiddle.net/deborah/Msvvr/

Well, hoping someone will be reading this, and save some time with it:) My goal was to make a small(as small as possible) js, that will take tableID, and put headers as fixed. It differs from what is given here with that it recalculates width with window.resize, so it allows tables to be resized dynamically, and no fixed sizes used from the start. And in theory - suppose to work with any table... (that was my case...)

function HeadsUp()
{
    var headers = $("#TheGrid tr").first();
    headers.css("margin-top", ((headers.height()+1)*-1)+"px");//edit +1 with what you want...
    headers.css("position", "absolute");
}

function ResizeHeaders()
{
    var grid = $("#TheGrid");
    var headers = $("#TheGrid tr").first();
    var firstdatarow = $("#TheGrid tr:nth-child(2)");
    headers.width(grid.width());

    var s = firstdatarow.children("td");
    var d = headers.children("th");//replace with td if you use it there
    for(i=0; i<s.length; i+=1) {
        d[i].width = s[i].clientWidth;
    }
}

$(function () {
HeadsUp();
ResizeHeaders();
});

$( window ).resize(function() {
ResizeHeaders();
});

The best option which worked for me is adding the following css properties to the th class in stylesheet.

th 
{
position: -webkit-sticky;
position: sticky;
top: 0px;
z-index: 5;
}

try this approach but it may not be the best way

<table style="top: 0px; position: fixed; z-index: 1; background-color: White">   
    <tr>   
      <th colspan="4">Current</th>   
      <th colspan="4">New/Requested</th>   
    </tr>    
    <tr>   
    <th nowrap="nowrap">RSD &nbsp;&nbsp;&nbsp;&nbsp;</th>  
    <th nowrap="nowrap">CRSD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
    <th nowrap="nowrap">MSD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
    <th nowrap="nowrap">Open QTY &nbsp;&nbsp;&nbsp;&nbsp;</th>   
    <th nowrap="nowrap">CRD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
    <th nowrap="nowrap">CRSD &nbsp;&nbsp;&nbsp;&nbsp;</th>  
    <th nowrap="nowrap">MSD &nbsp;&nbsp;&nbsp;&nbsp;</th>   
    <th nowrap="nowrap">Open QTY &nbsp;&nbsp;&nbsp;&nbsp;</th>   
    <th nowrap="nowrap">Action</th>   
    <th nowrap="nowrap">Reason</th>   
    <th nowrap="nowrap">Action Code Status </th>   
</tr> 
</table>
<table>
   <tbody>
      <tr>
        <td></td>  
        <td></td>   
        .....plenty of rows
      </tr>
   </tbody>
 </table>

what I did is just created another table for header and gave it fixed position

Using css

.fixhead
{ 
    position:relative
    overflow:auto;
}

And call this class in or in gridview headerrowstyle tag.

CSS PART----

 <style type="text/css">
    thead tr { position:relative; 
               top: expression(offsetParent.scrollTop); 
             }

  </style>

HTML PART----

<table width="100%" border="0" cellpadding="0" cellspacing="0" align="center">
    <thead>
     <tr>
      <td width="1%"></td>
      <td>ID</td>
      <td>Name</td>
     </tr>
    </thead>
    <tbody>
    //////////code
    </tbody>
    <tfoot>
    ////////code
    </tfott>
  </table>

Thanks

Set overflow: auto in the tbody's css.

so I had to create a similar component for my work. ( Note: admittedly I did this with jQuery but it can still be accomplished without it.)

The solution i came up with was similar and i thought i'd share it as it is much simplier

http://jsfiddle.net/YYaFr/6/

Basically you wrap the table in a div , copy it (the table) and make the first one just a header table (by removing the tbody ) and position it absolute.

<div class="containerdiv">
    <table class="headerTable">
        <colgroup>
            <col /> * number of columns
             ....
        </colgroup>
        <thead>
             <th></th>
             ....
        </thead>
    </table>
    <table class="dataTable">
        <colgroup>
            <col /> * number of columns
             ....
        </colgroup>
        <thead>
             <th></th>
             ....
        </thead>
        <tbody>
             <td></td>
             ....
        </tbody>
    </table>
</div>

and the css

div.containerDiv
{
    height: 300px; // Whatever height you need. can be set inline if you wish
}
div.containerDiv table.headerTable
{
    position: absolute;
}
div.containerDiv table.dataTable thead
{
    visibility: hidden; // This gives the header table room so it doesn't hide the first row.
}

Then the JavaScript basically creates the colgroups (or you can generate them server-side if you need.) Sets the widths and viola. That seems a lot simpler in my head so go ahead and check out the jsfiddle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM