<div class="container">
<div class="row">
<div class="col-12">
<h1>Display Flex & HTML5 Table with sticky headers</h1>
</div>
<div class="col-6">
<h2>HTML Table</h2>
<p>This is a native HTML Table that is scrollable with no sticky headers.</p>
<div class="table-scroll table-native">
<table class="table table-hover">
<thead>
<tr>
<th>one</th>
<th>two</th>
<th>three</th>
<th>four</th>
<th>five</th>
</tr>
</thead>
<tbody class="scroll">
<tr>
<td>r1 content 1</td>
<td>r1 content 2</td>
<td>r1 content 3</td>
<td>r1 content 4</td>
<td>r1 content 5</td>
</tr>
<tr>
<td>r2 content 1</td>
<td>r2 content 2</td>
<td>r2 content 3</td>
<td>r2 content 4</td>
<td>r2 content 5</td>
</tr>
<tr>
<td>r3 content 1</td>
<td>r3 content 2</td>
<td>r3 content 3</td>
<td>r3 content 4</td>
<td>r3 content 5</td>
</tr>
<tr>
<td>r4 content 1</td>
<td>r4 content 2</td>
<td>r4 content 3</td>
<td>r4 content 4</td>
<td>r4 content 5</td>
</tr>
<tr>
<td>r5 content 1</td>
<td>r5 content 2</td>
<td>r5 content 3</td>
<td>r5 content 4</td>
<td>r5 content 5</td>
</tr>
<tr>
<td>r6 content 1</td>
<td>r6 content 2</td>
<td>r6 content 3</td>
<td>r6 content 4</td>
<td>r6 content 5</td>
</tr>
<tr>
<td>r7 content 1</td>
<td>r7 content 2</td>
<td>r7 content 3</td>
<td>r7 content 4</td>
<td>r7 content 5</td>
</tr>
<tr>
<td>r8 content 1</td>
<td>r8 content 2</td>
<td>r8 content 3</td>
<td>r8 content 4</td>
<td>r8 content 5</td>
</tr>
<tr>
<td>r9 content 1</td>
<td>r9 content 2</td>
<td>r9 content 3</td>
<td>r9 content 4</td>
<td>r9 content 5</td>
</tr>
<tr>
<td>r10 content 1</td>
<td>r10 content 2</td>
<td>r10 content 3</td>
<td>r10 content 4</td>
<td>r10 content 5</td>
</tr>
<tr>
<td>r11 content 1</td>
<td>r11 content 2</td>
<td>r11 content 3</td>
<td>r11 content 4</td>
<td>r11 content 5</td>
</tr>
<tr>
<td>r12 content 1</td>
<td>r12 content 2</td>
<td>r12 content 3</td>
<td>r12 content 4</td>
<td>r12 content 5</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-6">
<h2>Flex Table with Sticky Headers</h2>
<p>This is a native HTML table utilizing CSS <code>flex</code> properties for sticky headers.</p>
<div class="table-scroll">
<table class="flex-table flex-table-aligned table table-striped table-hover">
<thead>
<tr>
<th>one</th>
<th>two</th>
<th>three</th>
<th>four</th>
<th>five</th>
</tr>
</thead>
<tbody class="scroll">
<tr>
<td>r1 content 1</td>
<td>r1 content 2</td>
<td>r1 content 3</td>
<td>r1 content 4</td>
<td>r1 content 5</td>
</tr>
<tr>
<td>r2 content 1</td>
<td>r2 content 2</td>
<td>r2 content 3</td>
<td>r2 content 4</td>
<td>r2 content 5</td>
</tr>
<tr>
<td>r3 content 1</td>
<td>r3 content 2</td>
<td>r3 content 3</td>
<td>r3 content 4</td>
<td>r3 content 5</td>
</tr>
<tr>
<td>r4 content 1</td>
<td>r4 content 2</td>
<td>r4 content 3</td>
<td>r4 content 4</td>
<td>r4 content 5</td>
</tr>
<tr>
<td>r5 content 1</td>
<td>r5 content 2</td>
<td>r5 content 3</td>
<td>r5 content 4</td>
<td>r5 content 5</td>
</tr>
<tr>
<td>r6 content 1</td>
<td>r6 content 2</td>
<td>r6 content 3</td>
<td>r6 content 4</td>
<td>r6 content 5</td>
</tr>
<tr>
<td>r7 content 1</td>
<td>r7 content 2</td>
<td>r7 content 3</td>
<td>r7 content 4</td>
<td>r7 content 5</td>
</tr>
<tr>
<td>r8 content 1</td>
<td>r8 content 2</td>
<td>r8 content 3</td>
<td>r8 content 4</td>
<td>r8 content 5</td>
</tr>
<tr>
<td>r9 content 1</td>
<td>r9 content 2</td>
<td>r9 content 3</td>
<td>r9 content 4</td>
<td>r9 content 5</td>
</tr>
<tr>
<td>r10 content 1</td>
<td>r10 content 2</td>
<td>r10 content 3</td>
<td>r10 content 4</td>
<td>r10 content 5</td>
</tr>
<tr>
<td>r11 content 1</td>
<td>r11 content 2</td>
<td>r11 content 3</td>
<td>r11 content 4</td>
<td>r11 content 5</td>
</tr>
<tr>
<td>r12 content 1</td>
<td>r12 content 2</td>
<td>r12 content 3</td>
<td>r12 content 4</td>
<td>r12 content 5</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h2>Setup</h2>
</div>
<div class="col-12">
<p>Add display flex.</p>
<ul>
<li>Add display flex with flex-direction column to the <code><table></code> & set height to 100% (will be 100% in relation to parent container)</li>
<li>Add display flex to <code><tr></code></li>
<li>Add display block to <code><thead></code> & <code><tbody></code> (support for internet explorer 9+ so columns align correctly)</li>
<li>Add overflow-y auto or scroll to <code><tbody></code> (so the table body only scrolls)</li>
<li>Add flex 1 to <code><tbody></code> (sets the table body to flex accordingly to height of table) ***we do not add a height or flex to the table header, ie <code><thead></code>, so the header elements will wrap correctly</li>
</ul>
</div>
<div class="col-6">
<h3>SCSS properties</h3>
<pre>
table.flex-table {
display: flex;
flex-direction: column;
height: 100%;
thead, tbody {
display: block;
}
tbody {
flex: 1;
overflow-y: scroll;
}
tr {
display: flex;
// flex-direction by default is row (optional)
flex-direction: row;
td, th {
// add display block for internet explorer 9+
display: block;
flex: 1;
// control column widths with :nth-child(n)
&:nth-child(n) {
flex: n;
}
}
}
}
</pre>
</div>
<div class="col-6">
<h3>Column Width</h3>
<p>Using <code>display: flex</code>, all columns will have a flex width of 1 by default. To dictate width of columns, use :nth-child(n) on tr>th, tr>td.</p>
<pre>
tr {
th,td {
// changing column 2 width
&:nth-child(2) {
flex: 3;
}
// changing column 4 width
&:nth-child(4) {
flex: 2;
}
}
}
</pre>
</div>
<div class="col-12">
<h3>Table with custom flex widths</h3>
<p>Example where column 2 makes use of <code>flex: 3</code> and column 4 makes use of <code>flex: 2</code> for custom column widths.</p>
<div class="table-scroll mb-3">
<table class="flex-table flex-widths table table-hover table-bordered">
<thead>
<tr>
<th>one</th>
<th>two <span class="badge bg-info text-dark"> ( flex width 3 ) </span></th>
<th>three</th>
<th>four <span class="badge bg-info text-dark"> ( flex width 2 ) </span></th>
<th>five</th>
</tr>
</thead>
<tbody class="scroll">
<tr>
<td>r1 content 1</td>
<td>r1 content 2</td>
<td>r1 content 3</td>
<td>r1 content 4</td>
<td>r1 content 5</td>
</tr>
<tr>
<td>r2 content 1</td>
<td>r2 content 2</td>
<td>r2 content 3</td>
<td>r2 content 4</td>
<td>r2 content 5</td>
</tr>
<tr>
<td>r3 content 1</td>
<td>r3 content 2</td>
<td>r3 content 3</td>
<td>r3 content 4</td>
<td>r3 content 5</td>
</tr>
<tr>
<td>r4 content 1</td>
<td>r4 content 2</td>
<td>r4 content 3</td>
<td>r4 content 4</td>
<td>r4 content 5</td>
</tr>
<tr>
<td>r5 content 1</td>
<td>r5 content 2</td>
<td>r5 content 3</td>
<td>r5 content 4</td>
<td>r5 content 5</td>
</tr>
<tr>
<td>r6 content 1</td>
<td>r6 content 2</td>
<td>r6 content 3</td>
<td>r6 content 4</td>
<td>r6 content 5</td>
</tr>
<tr>
<td>r7 content 1</td>
<td>r7 content 2</td>
<td>r7 content 3</td>
<td>r7 content 4</td>
<td>r7 content 5</td>
</tr>
<tr>
<td>r8 content 1</td>
<td>r8 content 2</td>
<td>r8 content 3</td>
<td>r8 content 4</td>
<td>r8 content 5</td>
</tr>
<tr>
<td>r9 content 1</td>
<td>r9 content 2</td>
<td>r9 content 3</td>
<td>r9 content 4</td>
<td>r9 content 5</td>
</tr>
<tr>
<td>r10 content 1</td>
<td>r10 content 2</td>
<td>r10 content 3</td>
<td>r10 content 4</td>
<td>r10 content 5</td>
</tr>
<tr>
<td>r11 content 1</td>
<td>r11 content 2</td>
<td>r11 content 3</td>
<td>r11 content 4</td>
<td>r11 content 5</td>
</tr>
<tr>
<td>r12 content 1</td>
<td>r12 content 2</td>
<td>r12 content 3</td>
<td>r12 content 4</td>
<td>r12 content 5</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-12">
<div class="row">
<div class="col-6">
<h3>Header alignment or lack thereof</h3>
<p>When the <code><tbody></code> has the overflow-y set to scroll, there will be a slight misalignment with the table headers and table body. To account for this misalignment, we can add an <code>overflow-y: scroll;</code> and <code>overflow-x: hidden</code> to our CSS <code>thead tr</code> selector.</p>
</div>
<div class="col-6">
<pre>
table {
thead > tr {
overflow-y: scroll;
overflow-x: hidden;
}
}
</pre>
</div>
</div>
</div>
<div class="col-12">
<div class="table-scroll mb-3">
<table class="flex-table table table-striped table-hover table-bordered flex-widths flex-table-aligned">
<thead>
<tr>
<th>one</th>
<th>two <span class="badge bg-info text-dark"> ( flex width 3 ) </span></th>
<th>three</th>
<th>four <span class="badge bg-info text-dark"> ( flex width 2 ) </span></th>
<th>five</th>
</tr>
</thead>
<tbody class="scroll">
<tr>
<td>r1 content 1</td>
<td>r1 content 2</td>
<td>r1 content 3</td>
<td>r1 content 4</td>
<td>r1 content 5</td>
</tr>
<tr>
<td>r2 content 1</td>
<td>r2 content 2</td>
<td>r2 content 3</td>
<td>r2 content 4</td>
<td>r2 content 5</td>
</tr>
<tr>
<td>r3 content 1</td>
<td>r3 content 2</td>
<td>r3 content 3</td>
<td>r3 content 4</td>
<td>r3 content 5</td>
</tr>
<tr>
<td>r4 content 1</td>
<td>r4 content 2</td>
<td>r4 content 3</td>
<td>r4 content 4</td>
<td>r4 content 5</td>
</tr>
<tr>
<td>r5 content 1</td>
<td>r5 content 2</td>
<td>r5 content 3</td>
<td>r5 content 4</td>
<td>r5 content 5</td>
</tr>
<tr>
<td>r6 content 1</td>
<td>r6 content 2</td>
<td>r6 content 3</td>
<td>r6 content 4</td>
<td>r6 content 5</td>
</tr>
<tr>
<td>r7 content 1</td>
<td>r7 content 2</td>
<td>r7 content 3</td>
<td>r7 content 4</td>
<td>r7 content 5</td>
</tr>
<tr>
<td>r8 content 1</td>
<td>r8 content 2</td>
<td>r8 content 3</td>
<td>r8 content 4</td>
<td>r8 content 5</td>
</tr>
<tr>
<td>r9 content 1</td>
<td>r9 content 2</td>
<td>r9 content 3</td>
<td>r9 content 4</td>
<td>r9 content 5</td>
</tr>
<tr>
<td>r10 content 1</td>
<td>r10 content 2</td>
<td>r10 content 3</td>
<td>r10 content 4</td>
<td>r10 content 5</td>
</tr>
<tr>
<td>r11 content 1</td>
<td>r11 content 2</td>
<td>r11 content 3</td>
<td>r11 content 4</td>
<td>r11 content 5</td>
</tr>
<tr>
<td>r12 content 1</td>
<td>r12 content 2</td>
<td>r12 content 3</td>
<td>r12 content 4</td>
<td>r12 content 5</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-12">
<h2>Additional resources</h2>
<p>For more info on CSS3 display flex, you can visit <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/flex">MDN</a>. You can also visit <a href="http://the-echoplex.net/flexyboxes/">echoplex</a> to see an interactive demo of flexbox in action.</p>
</div>
</div>
</div>
// table stylings
.table-scroll {
height: 300px;
padding: 0px;
&.table-native {
overflow-y: auto;
}
table {
&.flex-table {
display: flex;
flex-direction: column;
height: 100%;
thead,
tbody {
display: block;
}
thead {
margin-right: 0px; //margin to align correctly to scrollbar in table body
}
tbody {
flex: 1; //variable height
overflow-y: scroll;
}
tr {
width: 100%;
display: flex;
td,
th {
display: block;
flex: 1;
}
}
}
&.flex-widths {
tr {
td,
th {
&:nth-child(2) {
flex: 3;
}
&:nth-child(4) {
flex: 2;
}
}
}
}
&.flex-table-aligned {
thead > tr {
overflow-y: scroll;
overflow-x: hidden;
}
}
}
}
// table stylings end
// markup styling
pre {
background: #6c757d;
padding: 10px;
color: white;
}
code {
background: #6c757d;
padding: 3px 6px;
color: white;
}
View Compiled