I have a really large datatable and I want to put the horizontal scrollbar on top as well as on the bottom of the table so it would be easier for the user to scroll (the datatable has a lot of columns). Is there an easy and proper way to achieve this?
5 Answers
You can use a container that has a maximum width and put the table inside.
<div class="large-table-container-1">
<table>...</table>
</div>
Depending on how much reliability you want, you can make:
A. Bottom scrollbar, just set a maximum width and overflow x to scroll:
.large-table-container-1 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
Demo:
.large-table-container-1 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-container-1 table {
}
/*misc*/
td {
border: 1px solid gray;
}
th {
text-align: left;
}
<div class="large-table-container-1">
<table>
<thead>
<tr>
<th colspan="20">
Bottom scrollbar:
</th>
</tr>
</thead>
<tbody>
<tr>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
</tr>
</tbody>
</table>
</div>
B. Top scrollbar, a little hacky, use a 180 degree transform to rotate the scrollbar to the top, then again another 180 degree to put back the content.
.large-table-container-2 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
transform:rotateX(180deg);
}
.large-table-container-2 table {
transform:rotateX(180deg);
}
You may want to use broswser specific prefixes for transform, like -webkit-transform:rotateX(180deg);
.
Demo:
.large-table-container-2 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
transform:rotateX(180deg);
}
.large-table-container-2 table {
transform:rotateX(180deg);
}
/*misc*/
td {
border: 1px solid gray;
}
th {
text-align: left;
}
<div class="large-table-container-2">
<table>
<thead>
<tr>
<th colspan="20">
Top scrollbar:
</th>
</tr>
</thead>
<tbody>
<tr>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
</tr>
</tbody>
</table>
</div>
C. Top and bottom scrollbar, a little more hacky. Needs some javascript. Use the solution form A above and add a 'fake' div for top scrollbar:
<div class="large-table-fake-top-scroll-container-3">
<div> </div>
</div>
<div class="large-table-container-3">
<table>...</table>
</div>
.large-table-container-3 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-container-3 table {
}
.large-table-fake-top-scroll-container-3 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-fake-top-scroll-container-3 div {
background-color: red;/*Just for test, to see the 'fake' div*/
font-size:1px;
line-height:1px;
}
And a little javascript to catch the scroll on the top fake div and then scroll the table container (and vice-versa), with jQuery:
$(function() {
var tableContainer = $(".large-table-container-3");
var table = $(".large-table-container-3 table");
var fakeContainer = $(".large-table-fake-top-scroll-container-3");
var fakeDiv = $(".large-table-fake-top-scroll-container-3 div");
var tableWidth = table.width();
fakeDiv.width(tableWidth);
fakeContainer.scroll(function() {
tableContainer.scrollLeft(fakeContainer.scrollLeft());
});
})
Demo:
$(function() {
var tableContainer = $(".large-table-container-3");
var table = $(".large-table-container-3 table");
var fakeContainer = $(".large-table-fake-top-scroll-container-3");
var fakeDiv = $(".large-table-fake-top-scroll-container-3 div");
var tableWidth = table.width();
fakeDiv.width(tableWidth);
fakeContainer.scroll(function() {
tableContainer.scrollLeft(fakeContainer.scrollLeft());
});
tableContainer.scroll(function() {
fakeContainer.scrollLeft(tableContainer.scrollLeft());
});
})
.large-table-container-3 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-container-3 table {
}
.large-table-fake-top-scroll-container-3 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-fake-top-scroll-container-3 div {
background-color: red;
font-size:1px;
line-height:1px;
}
/*misc*/
td {
border: 1px solid gray;
}
th {
text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="large-table-fake-top-scroll-container-3">
<div> </div>
</div>
<div class="large-table-container-3">
<table>
<thead>
<tr>
<th colspan="20">
Top and bottom scrollbar:
</th>
</tr>
</thead>
<tbody>
<tr>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
</tr>
</tbody>
</table>
</div>
The working complete code for all three solutions:
$(function() {
var tableContainer = $(".large-table-container-3");
var table = $(".large-table-container-3 table");
var fakeContainer = $(".large-table-fake-top-scroll-container-3");
var fakeDiv = $(".large-table-fake-top-scroll-container-3 div");
var tableWidth = table.width();
fakeDiv.width(tableWidth);
fakeContainer.scroll(function() {
tableContainer.scrollLeft(fakeContainer.scrollLeft());
});
tableContainer.scroll(function() {
fakeContainer.scrollLeft(tableContainer.scrollLeft());
});
})
/*Bottom scrollbar*/
.large-table-container-1 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-container-1 table {
}
/*Top scrollbar*/
.large-table-container-2 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
transform:rotateX(180deg);
}
.large-table-container-2 table {
transform:rotateX(180deg);
}
/*Top and bottom scrollbar*/
.large-table-container-3 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-container-3 table {
}
.large-table-fake-top-scroll-container-3 {
max-width: 200px;
overflow-x: scroll;
overflow-y: auto;
}
.large-table-fake-top-scroll-container-3 div {
background-color: red;
font-size:1px;
line-height:1px;
}
/*misc*/
td {
border: 1px solid gray;
}
th {
text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="large-table-container-1">
<table>
<thead>
<tr>
<th colspan="20">
Bottom scrollbar:
</th>
</tr>
</thead>
<tbody>
<tr>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
</tr>
</tbody>
</table>
</div>
<div class="large-table-container-2">
<table>
<thead>
<tr>
<th colspan="20">
Top scrollbar:
</th>
</tr>
</thead>
<tbody>
<tr>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
</tr>
</tbody>
</table>
</div>
<div class="large-table-fake-top-scroll-container-3">
<div> </div>
</div>
<div class="large-table-container-3">
<table>
<thead>
<tr>
<th colspan="20">
Top and bottom scrollbar:
</th>
</tr>
</thead>
<tbody>
<tr>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>00</td>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
</tr>
</tbody>
</table>
</div>

- 7,981
- 3
- 36
- 42
-
Excellent answer with many approaches! I like it! However, fakeContainer.scroll() calls the other containers scroll(), which calls fakeContainer's scroll(), which creates an infinite loop, and I can no longer scroll long distances. I have a graphic of the problem and a solution here: https://stackoverflow.com/a/56384091/2430549 Still upvoting, because A and B approaches are flawless! – HoldOffHunger Jun 13 '19 at 19:31
-
Amazing answer! I had to massage my solution a little to this: var tableContainer = $(".dataTables_scrollBody"); using DataTables 1.10.20 – Cyrois Jul 08 '21 at 15:46
I found the solution to put scroll on top of table. Have look please: Demo in Fiddle Hope it would help.
`.dataTables_scrollBody {
transform:rotateX(180deg);
}
.dataTables_scrollBody table {
transform:rotateX(180deg);
}`
$(document).ready(function() {
$('#example').DataTable( {
scrollX : 'TRUE',
initComplete: function () {
this.api().columns().every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' )
} );
} );
}
} );
$('#example tfoot tr').insertAfter($('#example thead tr'));
} );

- 107
- 2
- 5
-
1Actually datatable is generating on html too. i wrote css code it will rotate table with html at 180(degree). Now table data and complete table will show in opposite direction. Than i just rotate inner table again now table is at fixed position and your scroll bar would be on top. For more have look to the FIDDLE link. – Abo Baker Sep 14 '18 at 10:47
-
I show scrollbar of the header with css/jQuery and set the body scrollLeft to the header's scroll left.
Example:
// Put top scroller
$('.dataTables_scrollHead').css({
'overflow-x':'scroll'
}).on('scroll', function(e){
var scrollBody = $(this).parent().find('.dataTables_scrollBody').get(0);
scrollBody.scrollLeft = this.scrollLeft;
$(scrollBody).trigger('scroll');
});

- 141
- 2
- 3
pls have a look at a similar query here:
horizontal scrollbar on top and bottom of table
This solution has worked for my datatable.
-
I cannot access the ID of the bottom scrollbar because it has been automatically added by datatables – msniezko Feb 02 '16 at 07:42
-
You can use overflow property in css.
You should separate body and header of your table in two different tables. then place the second table (body of original table) in a div and use overflow on this div.
<html>
<head>
<style>
.myOverflow {
height: 100px;
overflow-y: scroll;
display: inline-block;
}
</style>
</head>
<body>
<table id="HeaderTable">
<tr>
<td class="col1">Column1</td>
<td class="col2">Column2</td>
</tr>
</table>
<div class="myOverflow">
<table id="BodyTable">
<tr>
<td class="col1">a</td>
<td class="col2">b</td>
</tr>
<tr>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>e</td>
<td>f</td>
</tr>
</table>
</div>
</body>
</html>
<script>
</script>

- 1,625
- 2
- 19
- 32
-
-
-
This is a neat idea, Emad Armoun. But I think the OP was asking for a scrollbar on the top, while it seems you have put the header on the top and the scrollbar on the side. Your code is neat, but, not sure it'll work here. – HoldOffHunger Jun 13 '19 at 19:33