Reputation: 165
My goal is to fix the first column of a table and make the rest of the table scrollable horizontal.
See jsfiddle for reference: https://jsfiddle.net/e1thx7sj/4/ (scrolling omitted)
My main steps to reach this aim are:
This is the code:
var $table = $('.table');
// clone the table and insert it with an additional class
var $fixedColumn = $table.clone().insertBefore($table).addClass('fixed-column');
// remove all cells except of the first column cells
$fixedColumn.find('thead tr:first-child th:not(:first-child)').remove();
$fixedColumn.find('thead tr:not(:first-child) th').remove();
$fixedColumn.find('td:not(:first-child)').remove();
So far so good. But the heights of the rows in the "fixed column" don't fit to the row heights of the main table. It looks like this:
So I wrote a JS funtion (setRowHeightsEqualToBaseTable in jsfiddle) to adpat the row heights.
function setRowHeightsEqualToBaseTable() {
$fixedColumn.find('tr').each(function(i, elem) {
var $row = $(this);
var $fixedColumn = $row.parents('table');
var $baseTable = $fixedColumn.siblings('table:not(.fixed-column)');
var cellHeight = $baseTable.find('tr:eq(' + i + ')'[0].getBoundingClientRect().height;
$row.outerHeight(cellHeight);
});
}
This works perfectly. But not on iPhone Chrome / iPhone Safari.
Even if the css height attribute is set correctly (36px), the browser calculates another value for the height (56px).
I guess it has something to do with the line-height as this (20px) is the difference between the heights. But I can't figure out why there is this difference.
Upvotes: 2
Views: 336
Reputation: 106038
Instead remove()
to hide your cells, you should use css()
(visibility
or opacity
) , so not only structure but column's & row's size remains identical.
some z-index
have to be set and reset to keep content of your cells reacting to mouse events.
For a better interaction with the style, it might also be wised to set that clone one level higher (to deal with overflow:hidden
and then overflow:scroll
).
example
// get the table
var $table = $('.table');
// clone the table and insert it with an additional class
var $fixedColumn = $table.clone().insertBefore($table).addClass('fixed-column');
// remove all cells except of the first column cells
$fixedColumn.find('thead tr:first-child th:not(:first-child)').css('visibility', 'hidden');
$fixedColumn.find('thead tr:not(:first-child) th').css('visibility', 'hidden');
$fixedColumn.find('td:not(:first-child)').css('visibility', 'hidden');
setRowHeightsEqualToBaseTable();
/**
* Each tr in the fixed column should have the same height as the underlying table row.
*/
function setRowHeightsEqualToBaseTable() {
$fixedColumn.find('tr').each(function(i, elem) {
var $row = $(this);
var $fixedColumn = $row.parents('table');
var $baseTable = $fixedColumn.siblings('table:not(.fixed-column)');
var cellHeight = $baseTable.find('tr:eq(' + i + ')')[0].getBoundingClientRect().height;
$row.outerHeight(cellHeight);
});
}
/**
* On resize of the window the heights of table row may change - update view
*/
$(window).on('resize', function() {
setRowHeightsEqualToBaseTable();
});
.table-wrapper {
width:100%;
position: relative;
overflow:hidden;
}
.table-parent {
width:100%;
overflow:auto;
}
.fixed-column {
position: absolute;
left: 0;
}
.fixed-column th, .fixed-column td {
background-color: white;
border-right: 1px solid gray;
}
.table {
border: none;
border-collapse: separate;
display: table;
border-spacing: 0;
margin-bottom: 0;
max-width: 150%;
width: 150%;
background-color: transparent;
}
.table > thead > tr > th.first-col {
width: 130px !important;
min-width: 130px !important;
max-width: 130px !important;
}
.table tbody tr td {
border-left: 1px solid gray;
border-top: 1px solid gray;
}
.table tbody tr td:first-child {
border-left: none;
}
.table-parent > .table tr :first-child ~ *,
.table-wrapper .fixed-column tr :first-child {
background:white;
position:relative;
z-index:2
}
.table-wrapper .fixed-column tr :first-child {
z-index:3
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="table-wrapper">
<div class="table-parent">
<table class="table">
<thead>
<tr>
<th rowspan="2" class="first-col">Device Name,<br/>Product Brand</th>
<th rowspan="2">Lorem ipsum,<br/>Lorem ipsum</th>
<th rowspan="2" style="width: 100px;">Lorem ipsum</th>
<th colspan="4">Lorem ipsum</th>
<th rowspan="2" style="width: 70px;">Lorem ipsum</th>
<th rowspan="2" style="width: 40px;">Lorem ipsum</th>
</tr>
<tr>
<th style="width: 65px;">V</th>
<th style="width: 65px;">V</th>
<th style="width: 65px;">V</th>
<th style="width: 65px;">V</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#">A link</a></td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
</tr>
<tr>
<td><a href="#">A link</a></td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
</tr>
<tr>
<td><a href="#">A link</a></td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
</tr>
<tr>
<td><a href="#">A link</a></td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
<td>Lorem ipsum</td>
</tr>
</tbody>
</table>
</div>
</div>
https://jsfiddle.net/e1thx7sj/7/
Upvotes: 1