[jquery] DataTables fixed headers misaligned with columns in wide tables

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: 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!

This question is related to jquery datatables

The answer is


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.


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.


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


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>

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);

If you want to use scrollY use:

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


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();
})

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 );

});

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>'
} );

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.


I have fixed the column issue bu using below concept

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

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.


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
    }
});

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

.dataTables_scrollHeadInner
{
     width: 640px !important;
}

For bootstrap users, this fixed it for me:

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

See article here


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);

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


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.


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.


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
}