58

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!

Prashant Pokhriyal
  • 3,727
  • 4
  • 28
  • 40
bPratik
  • 6,894
  • 4
  • 36
  • 67

23 Answers23

18

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())});
Prashant Pokhriyal
  • 3,727
  • 4
  • 28
  • 40
Ruslans Uralovs
  • 1,122
  • 10
  • 18
  • Ruslans - this is a great start! Thanks! Could I ask if this solution can be tweaked to allow the `sScrollY` to be set? At the moment, if that is set, the header understandably displays below the wrapped table. – bPratik Aug 08 '13 at 10:30
  • So what you really want is for table to be scrolled both horizontally and vertically. In that case keep sScrollY and sScrollX properties commented out and just constrain the wrapping div to your required vertical size, e.g. 100px in the following Fiddle: http://jsfiddle.net/WZrCx/ – Ruslans Uralovs Aug 08 '13 at 14:14
  • Well, not quite! Using `sScrollY`, I can achieve a fixed header effect, whereas wrapping it doesn't. – bPratik Aug 08 '13 at 14:22
  • 2
    In that case you can do something like this: http://jsfiddle.net/ruslans_uralovs/zDaGk/ – Ruslans Uralovs Aug 12 '13 at 14:33
  • 1
    @RuslansUralovs: I find you last solution more efficient than one provided by DataTables. In case when table is set as some percentage from window width (90%) and window is resized so that both vertical and horizontal scrolling is needed, DataTables header starts to fall over. The only luxury which I cannot afford is duplication of data. Unfortunately some of the tables I have might be very big, so having DOM doubled is unaffordable. I'll try to implement the solution when "table with header" has no body, but on window resize the widths of the columns are copied from "table with body". – dma_k Jul 16 '14 at 14:53
  • @RuslansUralovs How to a column is fixed or not for a given column index? – Shamseer K Jan 12 '17 at 05:11
13

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>
Draykos
  • 773
  • 7
  • 16
  • Thanks. This hasn't fixed the issue for me yet, but it got me somewhere! – bPratik Nov 14 '12 at 10:43
  • Nice answer. I had a different problem but your code helped me fix it. The two first changes you said were the key. – Anth0 Apr 12 '13 at 08:20
4

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>'
} );
Mohanrajan
  • 721
  • 9
  • 18
4

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.

Ben Leitner
  • 1,532
  • 1
  • 12
  • 33
4

For bootstrap users, this fixed it for me:

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

See article here

Sam
  • 4,000
  • 20
  • 27
  • This should be the right answer. I just add the adjustment after the init is complete `$('.dataTable').dataTable().on( 'init', function () { $(this).columns.adjust() .fixedColumns().relayout(); })` – Aline Matos Jul 12 '18 at 02:38
2

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);
Vishnoo Rath
  • 550
  • 7
  • 22
2

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);
Earl
  • 31
  • 1
  • The answer just before proposes the same solution.. But us proved to not work... Please read bit more before posting! I would suggest deleting this answer. :-) – bPratik Jun 29 '13 at 02:33
2

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

});
bPratik
  • 6,894
  • 4
  • 36
  • 67
Divyanshu Rawat
  • 4,421
  • 2
  • 37
  • 53
  • If you try it on the fiddle provided, it doesn't work. – bPratik Jun 28 '16 at 10:48
  • just try it your in your editor initiating the search will auto. align header with column.you have down voted it just see if "bAutoWidth": is true or false in your table it might be some other issue post your code here I will solve it . – Divyanshu Rawat Jun 29 '16 at 12:42
  • 1
    .DataTable().draw() is sufficient, do not need ".search('') " in between – Akshay Vijay Jain Apr 03 '17 at 10:34
1

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.

Ah Hui
  • 41
  • 4
1

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();
})
Atul Baldaniya
  • 761
  • 8
  • 14
0

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.

Community
  • 1
  • 1
LeGEC
  • 46,477
  • 5
  • 57
  • 104
0

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
}
nikhil
  • 203
  • 1
  • 10
  • have you tried to apply it to the fiddle I have provided? – bPratik Aug 07 '14 at 22:17
  • let me try and provide you the link – nikhil Aug 07 '14 at 22:20
  • i had the same issue and this is how i got things straight ... so i thought i would share it – nikhil Aug 07 '14 at 22:21
  • Thanks for that, but as you will see from the plethora of other answers here that none of them work on my fiddle sample. They may have worked for that person! – bPratik Aug 07 '14 at 22:22
  • i am using jquery datatable version 1.10.0 and it works for me....but i donno why it dont work with the fiddle that you have provided. – nikhil Aug 07 '14 at 22:34
  • :) gremlins... Blame them gremlins! – bPratik Aug 07 '14 at 22:35
  • my answer is right., but it doesn't work in your case... can't get why.. sorry.... but please dont mark down the answer as wrong because it might be helpful to someone else – nikhil Aug 07 '14 at 22:36
  • Well, if I doubt it will. I would just remove it as basically it doesn't solve the question. – bPratik Aug 07 '14 at 22:37
0

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.

BulletVictim
  • 13
  • 1
  • 5
0

If you want to use scrollY use:

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

0

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

.dataTables_scrollHeadInner
{
     width: 640px !important;
}
Sanchi Girotra
  • 1,232
  • 13
  • 13
0

I have fixed the column issue bu using below concept

$(".panel-title a").click(function(){
    setTimeout( function(){
           $('#tblSValidationFilerGrid').DataTable().search( '' ).draw();
        }, 10 );
})
SantoshK
  • 1,789
  • 16
  • 24
0

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

0

Just add these two css

.dataTables_scrollHeadInner {
            width: 100% !important;
        }
        table.table.dataTable {
            width: 100% !important;
        }
Just add these two inside datatable js:
responsive: true,
scrollX: true,
0

I had same issue , I need to readjust table when header unfreeze so I have done something like below

$("body").on('DOMNodeRemoved', function(e) {
    //Readjust table when tag with class 'dtfh-floatingparent' removed 
    if($(e.target).hasClass("dtfh-floatingparent")){
        setTimeout(function(){
           $("#tableid").DataTable().columns.adjust().draw();
           //or if you have already datable instance you can use as below
           if(tableVar){
             tableVar.columns.adjust().draw();
           }  
        },100);
    }   
});

I hope this would help :)

Rohit Ramani
  • 776
  • 7
  • 15
-1

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.

tostasqb
  • 717
  • 1
  • 12
  • 28
-1

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.

Shalini
  • 219
  • 1
  • 5
  • 16
  • If you read the accepted answer, it had suggested that. But you lose the ability to have fixed headers. Hence this is not a solution. – bPratik Nov 19 '13 at 14:43
  • Yes.Still i didnt find solution for fixed header issue.But i got the scrollbar for datatables.When using scrollY if i adjust the scrollHeader height it works.but that's not a properway. – Shalini Nov 19 '13 at 15:18
-1

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

Firearm
  • 174
  • 1
  • 4
-1

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
    }
});
bPratik
  • 6,894
  • 4
  • 36
  • 67