Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed table header with horizontal AND vertical scrolling body

Objectives:

  • Column width of table header and table body should be same.
  • Table header to be fixed on vertical scroll.
  • Table header to be moved on horizontal scroll.
  • Header to be displayed inside scroll-able division of HTML.

Problem statements:

  • Table header does not get fixed on vertical scroll.
  • Header displayed out of scroll-able division of HTML(When header position is fixed).

I have seen many posts, but could not find the solution to this particular problem statement.

I have created two JSFiddles to demonstrate the problem statements:

Fiddle01: Solution works good as a separate module. JSFiddle01

Fiddle02: Solution does not work when its integrated with other divs. JSFiddle02

Any help would be very much appreciated.

$(function() {
var $window = $(window);
var $table = $('table');
var $head = $table.find('thead');
var $body = $table.find('tbody');
var $headTds1 = $head.find('tr').eq(0).find('th');
var $headTds2 = $head.find('tr').eq(1).find('th');
var $bodyTds = $body.find('tr').eq(0).find('td');
var tableWidth = $table.outerWidth();
// console.log("Width:"+tableWidth);
var $tableNew = $('<table/>');
var cl = 0; // colspan total length
var cc = 0; // colspan count

$table.css({ width: tableWidth });
$tableNew
    .attr("class", $table.attr("class"))
    .css({ width: tableWidth });

$head.css({ background: '#fff' });

$.each($headTds1, function(index, value) {
    var $headTd = $(value);
    var colspan = $headTd.attr('colspan') || 0;

    if (colspan) {
        while (colspan) {
            addwidth($($headTds2[cl]), $($bodyTds[index + cl - cc]));
            colspan--
            cl++
        }
        cc++;
    } else {
        addwidth($headTd, $($bodyTds[index + cl - cc]));
    }
});

function addwidth($headTd, $bodyTd) {
    var headTdwidth2 = $headTd.outerWidth();
    var bodyTdwidth2 = $bodyTd.outerWidth();
    var width2 = headTdwidth2 > bodyTdwidth2 ? headTdwidth2 : bodyTdwidth2;

    $bodyTd.css({ 'width': width2 });
    $headTd.css({ 'width': width2 });

    var headTdwidth = $headTd.width();
    var bodyTdwidth = $bodyTd.width();
    var width = headTdwidth > bodyTdwidth ? headTdwidth : bodyTdwidth;
    $bodyTd.html('<div style="width: ' + width + 'px">' + $bodyTd.html() + '</div>');
    $headTd.html('<div style="width: ' + width + 'px">' + $headTd.html() + '</div>');
}

$head.appendTo($tableNew);
$tableNew.insertBefore($table);
// $table.css({ 'margin-top': $tableNew.height() });

$tableNew.css({ position: 'fixed' });

$window.scroll(reLeft);
$window.resize(reLeft);


function reLeft() {
    $tableNew.css({ left: $table.offset().left - $window.scrollLeft() });
}
});
like image 345
WEshruth Avatar asked Feb 04 '23 20:02

WEshruth


2 Answers

You are cloning the table for fix header, better you can direct fix the header of original table which will results the same.

Element with position:fixed changes the width with respect to viewport, which results width gets change on scrolling as you can check here https://jsfiddle.net/chourasiapawankumar/vg7q3tyc/19

Approach:1

instead of position:fixed use relative in th and it is working with your parent div which has min-height:100px.

https://jsfiddle.net/chourasiapawankumar/krw0qpbL/62/

Approach:2

You can see both horizontal and vertical scroll bar at a time on removing min-height of parent div which I have commented in the below fiddle.

https://jsfiddle.net/chourasiapawankumar/vg7q3tyc/33/

like image 125
Pawan Kumar Avatar answered Feb 06 '23 16:02

Pawan Kumar


Dunno if you can/want to use a library, but floatHead works nicely and it looks like it does what you want... Go on the linked page and click the Demo "Run FloatHead" button, you will see it in action.

like image 23
JBA Avatar answered Feb 06 '23 16:02

JBA