Reputation: 23
I am trying to implement an HTML table that could have a sticky column(s) and a sticky header at the same time, using javascript and css.
Basically I am trying to ensure the stickiness of the header and the columns by translating them at the right position whenever the scroll position is changed.
This technique works fine, when I scroll horizontally the sticky columns are properly displayed at the fixed position, but when I start scrolling vertically the sticky column cells overlap the header cells and hide them.
Here is what I am seeing when it happens
I tried to play with the z-index to make sure the header is always on top of the rows, but for some reason it's not working.
If anyone ever encountered this issue and could share a way to fix it, that would be really appreciated.
Thanks in advance.
HTML:
<table class="tablesorter">
<thead class="sticky-header">
<tr>
<th class="sticky-column">Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
...
</tr>
</thead>
<tbody>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
...
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
...
</tr>
</tbody>
</table>
Javascript:
var $win = $(window),
$stickyHeader = $('.sticky-header'),
$stickyColumns = $('.sticky-column');
$(document).on('scroll', function () {
deltaY = $win.scrollTop() - $stickyHeader.offset().top;
deltaX = $win.scrollLeft() - $stickyHeader.offset().left;
$stickyHeader.children().css({
"transform": "translate(0px," + (deltaY > 0 ? deltaY : 0) +
"px)"
});
$stickyColumns.css({
"transform": "translate(" + (deltaX > 0 ? deltaX : 0) + "px,
0px)"
});
});
CSS:
table {
margin: 100px auto 800px auto;
}
thead th {
background-color: yellow;
border-right: 2px solid black;
border-left: 2px solid black;
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 60px;
z-index: 3;
}
tbody td {
background-color: red;
border-right: 2px solid black;
border-left: 2px solid black;
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 30px;
z-index: 1;
}
tbody td.sticky-column {
z-index: 2;
}
tbody th.sticky-column {
z-index: 4;
}
Here is the JSFiddle reproducing the issue: http://jsfiddle.net/asoua/5942rqty/
Upvotes: 2
Views: 10166
Reputation: 4437
This is a solution for a HTML table with sticky columns and rows headers, using only CSS. For more info you can check here.
/* set some spacing (optional)*/
td,
th {
padding: 20px;
}
/* style columns table headings*/
th[scope=col] {
position: -webkit-sticky;
position: sticky;
top: 0;
z-index: 1;
background-color: teal;
}
/* style columns headings first element*/
th[scope=col]:nth-of-type(1) {
position: -webkit-sticky;
position: sticky;
top: 0;
left: 0;
z-index: 2;
background-color: peru;
}
/* style rows table headings*/
th[scope=row] {
position: -webkit-sticky;
position: sticky;
left: 0;
z-index: 1;
background-color: chocolate;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sales</title>
</head>
<body>
<h1>ACME Company</h1>
<table>
<tr>
<th scope="col">Sales by Country</th>
<th scope="col">January</th>
<th scope="col">February</th>
<th scope="col">March</th>
<th scope="col">April</th>
<th scope="col">May</th>
<th scope="col">June</th>
<th scope="col">July</th>
<th scope="col">August</th>
<th scope="col">September</th>
<th scope="col">October</th>
<th scope="col">November</th>
<th scope="col">December</th>
</tr>
<tr>
<th scope="row">Portugal</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Spain</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">France</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Germany</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Italy</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Poland</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Austria</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">United States</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">England</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Scotland</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
<tr>
<th scope="row">Wales</th>
<td>50.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
<td>52.000</td>
</tr>
</table>
</body>
</html>
Upvotes: 0
Reputation: 719
try this sollution
.sticky-header {
position: absolute;
z-index: 4;
}
i suggest to use grid unstead of table
Upvotes: 1
Reputation: 6824
I used a combination of z-index, and a change to your logic to get it working. That corner column needs both and x and y axis transforms.
var $win = $(window),
$stickyHeader = $('.sticky-header'),
$stickyColumns = $('.sticky-column'),
$stickyCorner = $('.sticky-corner');
$(document).on('scroll', function () {
deltaY = $win.scrollTop() - $stickyHeader.offset().top;
deltaX = $win.scrollLeft() - $stickyHeader.offset().left;
$stickyColumns.css({
"transform": "translate(" + (deltaX > 0 ? deltaX : 0) + "px, 0px)"
});
$stickyHeader.children().css({
"transform": "translate(0px," + (deltaY > 0 ? deltaY : 0) + "px)"
});
$stickyCorner.css({
"transform": "translate(" + (deltaX > 0 ? deltaX : 0) + "px," + (deltaY > 0 ? deltaY : 0) + "px)"
});
});
table {
margin: 100px auto 800px auto;
}
thead th {
background-color: yellow;
border-right: 2px solid black;
border-left: 2px solid black;
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 60px;
z-index: 3;
}
tbody td {
background-color: red;
border-right: 2px solid black;
border-left: 2px solid black;
border-bottom: 1px solid black;
border-top: 1px solid black;
height: 30px;
z-index: 1;
}
tbody td.sticky-column {
z-index: 1;
}
thead tr.sticky-column {
z-index: 2;
}
thead th.sticky-corner {
background-color: orange;
z-index: 10;
position: relative;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="tablesorter">
<thead>
<tr class="sticky-header">
<th class="sticky-corner">Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
<th>Whatever Header</th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
<tr>
<td class="sticky-column">Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
<td>Whatever</td>
</tr>
</tbody>
</table>
Upvotes: 2
Reputation: 584
You can use the following attributes:
position: -webkit-sticky; /* for Safari */
position: sticky;
If you use this for example on the first child of a column, or a the full header, it will make your desire effect.
<tbody>
<tr>
<th>Whatever</th>
<td>Whatever</td>
...
</tr>
<tr>
<th>Whatever</th>
<td>Whatever</td>
...
</tr>
</tbody>
thead th {
z-index:999;
top:0;
position: -webkit-sticky;
position: sticky;
}
tbody th {
left:0;
position: -webkit-sticky;
position: sticky;
}
tbody th:first-child {
position: -webkit-sticky;
position: sticky;
z-index: 999;
left:0;
}
Try it!
Upvotes: 0