DataTables fixed headers misaligned with columns in wide tables

JqueryDatatables

Jquery Problem Overview


Problem

When using the sScrollX, sScrollXInner and/or sScrollY to achieve a fixed header table with its inner content scrolling, the headers of the table go out of alignment with the rest of the body in Chrome and IE. Firefox, on the other hand, displays them perfectly.

Using the version 1.9.4, as far as I can tell, this issue only occurs when there is a lot of data with fluctuating widths, and with words that are very long/unwrappable combined in the same columns as small ones. Also, the table in question needs to be fairly wide.

All these factors are demonstrated in this fiddle:

Output

Chrome:
Chrome Screenshot

IE:
IE9 Screenshot

Firefox
Firefox Screenshot

Suggested Solutions

These solutions have been suggested before but have had no effect on my implementation. Owing to some of these suggestions, I setup a clean plain vanilla demo as I wanted to ensure that no other code was contributing to this effect.

  • turn-off/remove all my css
  • setTimeout( function () { oTable.fnAdjustColumnSizing(); }, 10 );
  • calling oTable.fnFilter( "x",0 ) and oTable.fnFilter( "",0 ) in that order
  • "sScrollXInner": "100%"
  • get rid of all widths

The only solution that I found to the misaligned headers was taking out sScrollX and sScrollY, but this can't be counted as a solution as you lose the fixed header/inner content scrolling functionality. So sadly it's a temporary hack, not a fix!

Note

To edit/play with the latest fiddle.

I have tried various combinations which can be observed in the revision history of the fiddle by using the link http://jsfiddle.net/pratik136/etL73/#REV# where 1 <= #REV# <= 12

History

StackO
This question has been asked before: https://stackoverflow.com/questions/8607290/jquery-datatables-header-misaligned-with-vertical-scrolling
but the vital difference is that the OP of that question mentioned that they were able to fix the issue if all CSS was removed, which is untrue in my case, and I have tried a few permutations, thus thought the question worthy of a repost.

External
This issue has also been flagged on the DataTables forum:

This issue has driven me nuts! Please contribute your thoughts!

Jquery Solutions


Solution 1 - Jquery

EDIT: See the latest Fiddle with "fixed header":


The Fiddle.

One of the solutions is to implement scrolling yourself instead of letting DataTables plugin do it for you.

I've taken your example and commented out sScrollX option. When this option is not present DataTables plugin will simply put your table as is into a container div. This table will stretch out of the screen, therefore, to fix that we can put it into a div with required width and an overflow property set - this is exactly what the last jQuery statement does - it wraps existing table into a 300px wide div. You probably will not need to set the width on the wrapping div at all (300px in this example), I have it here so that clipping effect is easily visible. And be nice, don't forget to replace that inline style with a class.

$(document).ready(function() {
var stdTable1 = $(".standard-grid1").dataTable({
    "iDisplayLength": -1,
    "bPaginate": true,
    "iCookieDuration": 60,
    "bStateSave": false,
    "bAutoWidth": false,
    //true
    "bScrollAutoCss": true,
    "bProcessing": true,
    "bRetrieve": true,
    "bJQueryUI": true,
    //"sDom": 't',
    "sDom": '<"H"CTrf>t<"F"lip>',
    "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
    //"sScrollY": "500px",
    //"sScrollX": "100%",
    "sScrollXInner": "110%",
    "fnInitComplete": function() {
        this.css("visibility", "visible");
    }
});

var tableId = 'PeopleIndexTable';
$('<div style="width: 300px; overflow: auto"></div>').append($('#' + tableId)).insertAfter($('#' + tableId + '_wrapper div').first())});

Solution 2 - Jquery

The following is a way to achieve a fixed header table, I don't know if it will be enough for your purpose. Changes are:

  1. use "bScrollCollapse" instead of "sScrollXInner"
  2. don't use fieldset to wrap table
  3. add a "div.box" css class

It seems fully working on my local machine, but it's not fully working using Fiddle. It seems that Fiddle adds a css file (normalize.css) that in some way broke the plugin css (quite sure I can make fully working also in Fiddle adding some css clear rules, but not have time to investigate further now)

My working code snippet is below. Hope this can help.

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">

  <script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
  <script type='text/javascript' src="http://datatables.net/release-datatables/media/js/jquery.dataTables.min.js"></script>

 <style type='text/css'>
       div.box {
	   height: 100px;
	   padding: 10px;
	   overflow: auto;
	   border: 1px solid #8080FF;
	   background-color: #E5E5FF;
   }

  .standard-grid1, .standard-grid1 td, .standard-grid1 th {
    border: solid black thin;
   }
</style>
    
<script type='text/javascript'> 
$(window).load(function(){
$(document).ready(function() {
    var stdTable1 = $(".standard-grid1").dataTable({
        "iDisplayLength": -1,
        "bPaginate": true,
        "iCookieDuration": 60,
        "bStateSave": false,
        "bAutoWidth": false,
        //true
        "bScrollAutoCss": true,
        "bProcessing": true,
        "bRetrieve": true,
        "bJQueryUI": true,
        "sDom": '<"H"CTrf>t<"F"lip>',
        "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
        "sScrollX": "100%",
        //"sScrollXInner": "110%",
		"bScrollCollapse": true,
        "fnInitComplete": function() {
            this.css("visibility", "visible");
        }
    });
});
});

</script>


</head>
<body>
<div>
    <table class="standard-grid1 full-width content-scrollable" id="PeopleIndexTable">
        <thead>
          <!-- put your table header HTML here -->
       </thead>
       <tbody>
          <!-- put your table body HTML here -->
        </tbody>
    </table>
</div>
</body>
</html>

Solution 3 - Jquery

I am having the same issue on IE9.

I will just use a RegExp to strip all the white spaces before writing the HTML to the page.

var Tables=$('##table_ID').html();
var expr = new RegExp('>[ \t\r\n\v\f]*<', 'g');
Tables= Tables.replace(expr, '><');
$('##table_ID').html(Tables);
oTable = $('##table_ID').dataTable( {
  "bPaginate": false,
  "bLengthChange": false,
  "bFilter": false,
  "bSort": true,
  "bInfo": true,
  "bAutoWidth": false,
  "sScrollY": ($(window).height() - 320),
  "sScrollX": "100%",
  "iDisplayLength":-1,
  "sDom": 'rt<"bottom"i flp>'
} );

Solution 4 - Jquery

Adding these two lines fixed this problem for me

"responsive": true,
"bAutoWidth": true

There is now a responsive plugin available: https://datatables.net/extensions/responsive/. However, in my experience I have found that there are still a few bugs. It's still the best solution I've found so far.

Solution 5 - Jquery

For bootstrap users, this fixed it for me:

   $($.fn.dataTable.tables(true)).DataTable()
      .columns.adjust()
      .fixedColumns().relayout();

See article here

Solution 6 - Jquery

The code below worked. Corrected the issue on I.E 9.0 atleast. Hope this helps

var oTable =  $('#tblList').dataTable({
    "sScrollY": "320px",
    "bScrollCollapse": true,
    });

    setTimeout(function(){
        oTable.fnAdjustColumnSizing();
    },10);

Solution 7 - Jquery

I had the same problem and this code solves it. I got this solution from this article but I had to adjust the time on the interval for it to work.

setTimeout(function(){
        oTable.fnAdjustColumnSizing();
},50);

Solution 8 - Jquery

Trigger DataTable search function after initializing DataTable with a blank string in it. It will automatically adjust misalignment of thead with tbody.

$( document ).ready(function()
{

    $('#monitor_data_voyage').DataTable( {
        scrollY:150,
        bSort:false,
        bPaginate:false,
        sScrollX: "100%",
        scrollX: true,
    } );

    setTimeout( function(){
       $('#monitor_data_voyage').DataTable().search( '' ).draw();
    }, 10 );

});

Solution 9 - Jquery

try this, the following code solved my problem

table.dataTable tbody th,table.dataTable tbody td 
{
     white-space: nowrap;
} 

for more information pls refer Here.

Solution 10 - Jquery

I use this for Automatic column hiding as per column data, in that case, sometimes its break table structure. i solve that problem with this $($.fn.dataTable.tables(true)).DataTable().columns.adjust(); and this function $('#datatableId').on('draw.dt', function () { }); call after tabledata load.

$('#datatableId').on('draw.dt', function () {
	$($.fn.dataTable.tables(true)).DataTable().columns.adjust();
})

Solution 11 - Jquery

Add table-layout: fixed to your table's style (css or style attribute).

The browser will stop applying its custom algorithm to solve size constraints.

Search the web for infos about handling column widths in a fixed table layout (here are 2 simple SO questions : here and here)

Obviously: the downside will be that your columns' width won't adapt to their content.


[Edit] My answer worked when I used the FixedHeader plugin, but a post on the datatable's forum seem to indicate that other problems arise when using the sScrollX option :

bAutoWidth and sWidth ignored when sScrollX is set (v1.7.5)

I'll try to find a way to go around this.

Solution 12 - Jquery

try this

this works for me... i added the css for my solution and it works... although i didnt change anything in datatable css except { border-collapse: separate;}

.dataTables_scrollHeadInner {    /*for positioning header when scrolling is applied*/
padding:0% ! important
}

Solution 13 - Jquery

I know there has been an answer flagged already, but for someone with similar problems that the above does not work for. I'm using it in conjunction with bootstrap theme.

There is a line that can be altered in the dataTables.fixedHeader.js file. the default layout of the function looks as follows.

    _matchWidths: function (from, to) {
        var get = function (name) {
            return $(name, from)
                .map(function () {
                    return $(this).width();
                }).toArray();
        };

        var set = function (name, toWidths) {
            $(name, to).each(function (i) {
                $(this).css({
                    width: toWidths[i],
                    minWidth: toWidths[i]
                });
            });
        };

        var thWidths = get('th');
        var tdWidths = get('td');

        set('th', thWidths);
        set('td', tdWidths);
    },

change the

    return $(this).width();

to

    return $(this).outerWidth();

outerWidth() is a function that is contained in jquery.dimensions.js if you are usingg a newer version of jquery. ie. jquery-3.1.1.js

what the above function does is it maps the th of the original table, then applies them to the "cloned" table(fixed header). in my case they were always off by about 5px to 8px when misaligned. Most probably not the best fix out there but provides a solution to all other tables in the solution without having to specify it per table declaration. It has only been tested in Chrome so far, but it should provide an adjudicate solution on all browsers.

Solution 14 - Jquery

If you want to use scrollY use:

$('.DataTables_sort_wrapper').trigger("click");

Solution 15 - Jquery

I fixed the same issue in my application by adding below code in the css -

.dataTables_scrollHeadInner
{
     width: 640px !important;
}

Solution 16 - Jquery

I have fixed the column issue bu using below concept

$(".panel-title a").click(function(){
	setTimeout( function(){
	       $('#tblSValidationFilerGrid').DataTable().search( '' ).draw();
	    }, 10 );
})

Solution 17 - Jquery

After trying everything I could, I just added "autoWidth": true and it worked for me.

Solution 18 - Jquery

Faced the same issue recently and was still searching for the solution when I tried something on my css, check if adding to your cells (th and td)

-webkit-box-sizing: content-box; 
-moz-box-sizing: content-box;  
-sizing: content-box;

will resolve this issue; for me, I was using some html/css framework that was adding a the value border-box in every element.

Solution 19 - Jquery

Instead using sScrollX,sScrollY use separate div style

.scrollStyle
 {
  height:200px;overflow-x:auto;overflow-y:scroll;
 }

Add below after datatable call in script

 jQuery('.dataTable').wrap('<div class="scrollStyle" />');

Its working perfectly after many tries.

Solution 20 - Jquery

I had this very same problem and seen a lot of complicated answers that never seemed to work. I did solve it by simply overriding the CSS (site.css) on the following and it fixed it in Chrome, IE, and Firefox:

table.display td {
padding: 0px 5px;
}
/* this is needed for IE and Firefox if using horizontal scroll*/
table{
    max-width: none;
    min-height: 0%;
}

This overrides the CSS in datatable.jui.css

Solution 21 - Jquery

I just figured out a way to fix the alignment issue. Changing the width of div containing the static header will fix its alignment. The optimal width I found is 98%. Please refer to the code.

The auto generated div:

<div class="dataTables_scrollHead" style="overflow: hidden; position: relative; border: 0px none; width: 100%;">

Width here is 100%, change it to 98% on initializing and reloading the data table.

jQuery('#dashboard').dataTable({
    "sEcho": "1",

    "aaSorting": [[aasortvalue, 'desc']],
    "bServerSide": true,
    "sAjaxSource": "NF.do?method=loadData&Table=dashboardReport",
    "bProcessing": true,
    "sPaginationType": "full_numbers",
    "sDom": "lrtip", // Add 'f' to add back in filtering
    "bJQueryUI": false,
    "sScrollX": "100%",
    "sScrollY": "450px",
    "iDisplayLength": '<%=recordCount%>',
    "bScrollCollapse": true,
    "bScrollAutoCss": true,
    "fnInitComplete": function () {
        jQuery('.dataTables_scrollHead').css('width', '98%'); //changing the width
    },
    "fnDrawCallback": function () {
        jQuery('.dataTables_scrollHead').css('width', '98%');//changing the width
    }
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbPratikView Question on Stackoverflow
Solution 1 - JqueryRuslans UralovsView Answer on Stackoverflow
Solution 2 - JqueryDraykosView Answer on Stackoverflow
Solution 3 - JqueryMohanrajanView Answer on Stackoverflow
Solution 4 - JqueryBen LeitnerView Answer on Stackoverflow
Solution 5 - JquerySamView Answer on Stackoverflow
Solution 6 - JqueryVishnoo RathView Answer on Stackoverflow
Solution 7 - JqueryEarlView Answer on Stackoverflow
Solution 8 - JqueryDivyanshu RawatView Answer on Stackoverflow
Solution 9 - JqueryAh HuiView Answer on Stackoverflow
Solution 10 - JqueryAtul BaldaniyaView Answer on Stackoverflow
Solution 11 - JqueryLeGECView Answer on Stackoverflow
Solution 12 - JquerynikhilView Answer on Stackoverflow
Solution 13 - JqueryBulletVictimView Answer on Stackoverflow
Solution 14 - JqueryVictor VillacortaView Answer on Stackoverflow
Solution 15 - JquerySanchi GirotraView Answer on Stackoverflow
Solution 16 - JquerySantoshKView Answer on Stackoverflow
Solution 17 - Jqueryuser3055896View Answer on Stackoverflow
Solution 18 - JquerytostasqbView Answer on Stackoverflow
Solution 19 - JqueryShaliniView Answer on Stackoverflow
Solution 20 - JqueryFirearmView Answer on Stackoverflow
Solution 21 - JqueryPranav RajView Answer on Stackoverflow