Skip to content

Instantly share code, notes, and snippets.

@0x3333
Last active Apr 5, 2019
Embed
What would you like to do?
Bootstrap Table Fixed Header with Footer

Table Fixed Header

This is to mimic a Table with fixed header at top and a footer.

Different from other options in the internet, this is not automatic layout. You have to build the HTML following the structure above.

This table has rounded corners and the CSS is customized to remove double borders.

Columns width can be px or %, the table-layout is fixed. The table can scroll horizontally and vertically. Fixed the vertical scroll bar not been take in consideration. Now the table will scroll and the header/footer will be aligned correctly.

Also I added a simple way to select a row.

Example: http://jsfiddle.net/0x3333/f0vfpvLm/4/

<div class="table-container">
   <-- Header -->
   <div class="table-container-header">
      <table class="table table-bordered">
         <thead>
            <tr>
              <th>Header 1</th>
              ...
              <th>Header N</th>
            </tr>
         </thead>
      </table>
   </div>
   <-- Body -->
   <div class="table-container-body">
      <table class="table table-bordered">
         <-- You set the columns width here -->
         <colgroup>
            <col style="width: XXXpx;"></col>
            ...
            <col style="width: XXX%;"></col>
         </colgroup>
         <tbody>
            <tr>
              <td>Body 1</td>
              ...
              <td>Body N</td>
            </tr>
         </tbody>
      </table>
   </div>
   <!-- Optional -->
   <-- Footer -->
   <div class="table-container-footer">
      <table class="table table-striped table-hover table-condensed table-bordered">
         <tfoot>
            <tr>
              <th>Footer 1</th>
              ...
              <th>Footer N</th>
            </tr>
         </tfoot>
      </table>
   </div>
</div>
p.fixed-table-scroll-inner {
width: 100%;
height: 200px;
}
div.fixed-table-scroll-outer {
top: 0;
left: 0;
visibility: hidden;
width: 200px;
height: 150px;
overflow: hidden;
}
.table-container {
border: 1px solid #ddd;
border-radius: 5px;
margin: 10px;
overflow: hidden;
}
.table-container-header {
overflow: hidden;
width: 100%;
}
.table-container-body {
height: 154px;
overflow: auto;
width: 100%;
}
.table-container-footer {
overflow: hidden;
width: 100%;
}
.table-container table {
margin-bottom: 0px;
table-layout: fixed;
}
.table-container table td,
.table-container table th {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.table-bordered {
border: 0px;
}
.table-bordered > thead > tr > th,
.table-bordered > thead > tr > td {
border-bottom-width: 2px;
}
.table-bordered > tfoot > tr > th,
.table-bordered > tfoot > tr > td {
border-top-width: 2px;
}
.table-bordered > tfoot > tr > th,
.table-bordered > tfoot > tr > td {
border-bottom-width: 0px;
}
/*Left*/
.table-bordered > thead > tr > th:first-child,
.table-bordered > tbody > tr > th:first-child,
.table-bordered > tfoot > tr > th:first-child,
.table-bordered > thead > tr > td:first-child,
.table-bordered > tbody > tr > td:first-child,
.table-bordered > tfoot > tr > td:first-child {
border-left-width: 0px;
}
/*Right*/
.table-bordered > thead > tr > th:last-child,
.table-bordered > tbody > tr > th:last-child,
.table-bordered > tfoot > tr > th:last-child,
.table-bordered > thead > tr > td:last-child,
.table-bordered > tbody > tr > td:last-child,
.table-bordered > tfoot > tr > td:last-child {
border-right-width: 0px;
}
/*Top*/
.table-bordered > thead > tr:first-child > th,
.table-bordered > thead > tr:first-child > td {
border-top-width: 0px;
}
/*Bottom*/
.table-bordered > tfoot > tr:last-child > th,
.table-bordered > tfoot > tr:last-child > td {
border-bottom-width: 0px;
}
<div class="table-container">
<div class="table-container-header">
<table class="table table-striped table-hover table-condensed table-bordered">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
</table>
</div>
<div class="table-container-body">
<table class="table table-striped table-hover table-condensed table-bordered">
<colgroup>
<col style="width: 20px;"></col>
<col style="width: 100px;"></col>
<col style="width: 200px;"></col>
<col style="width: 150px;"></col>
</colgroup>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>4</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>5</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>6</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>7</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>8</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>9</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>10</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container-footer">
<table class="table table-striped table-hover table-condensed table-bordered">
<tfoot>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</tfoot>
</table>
</div>
</div>
var $body = $(".table-container-body"),
$header = $(".table-container-header"),
$footer = $(".table-container-footer");
// Get ScrollBar width(From: http://bootstrap-table.wenzhixin.net.cn/)
var scrollBarWidth = (function () {
var inner = $('<p/>').addClass('fixed-table-scroll-inner'),
outer = $('<div/>').addClass('fixed-table-scroll-outer'),
w1, w2;
outer.append(inner);
$('body').append(outer);
w1 = inner[0].offsetWidth;
outer.css('overflow', 'scroll');
w2 = inner[0].offsetWidth;
if (w1 === w2) {
w2 = outer[0].clientWidth;
}
outer.remove();
return w1 - w2;
})();
// Scroll horizontal
$body.on('scroll', function () {
$header.scrollLeft($(this).scrollLeft());
$footer.scrollLeft($(this).scrollLeft());
});
// Redraw Header/Footer
var redraw = function() {
var tds = $body.find("> table > tbody > tr:first-child > td");
tds.each(function (i) {
var width = $(this).innerWidth(),
lastPadding = tds.length -1 == i ? scrollBarWidth : 0;
lastHeader = $header.find("th:eq("+i+")").innerWidth(width + lastPadding);
lastFooter = $footer.find("th:eq("+i+")").innerWidth(width + lastPadding);
});
};
// Selection
$body.find("> table > tbody > tr > td").click(function(e) {
$body.find("> table > tbody > tr").removeClass("info");
$(e.target).parent().addClass('info');
});
// Listen to Resize Window
$(window).resize(redraw);
redraw();
@tanobi92
Copy link

tanobi92 commented Apr 22, 2015

Hi @0x3333, I'm using code of you for my Table. My table have multi th.
https://www.dropbox.com/s/wmafxbqnmwi0t4w/Screenshot%202015-04-22%2016.41.04.png?dl=0
But the Thead and Tbody are mismatch.
I hope you help me, pls!
Thank you very much!
Demo:http://jsfiddle.net/TaNoBi/av6Lp7t7/

@dushaun
Copy link

dushaun commented Nov 24, 2016

Does this work on Windows machines? I've used your example and it doesn't seem to be working in Chrome on Windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment