javascript - How to create an html <table> that has a fixed header **and** pinned columns using primarily CSS -
i've had luck applying css transform on scroll in order have fixed table header. try same technique when scrolling horizontally have pinned columns.
the problem i'm running pinned columns in header appear behind instead of on top when scrolling horizontally. browser deciding dom elements should on top after doing transformation. can control this? (yes, i've tried z-index)
demo
(function() { var app = angular.module("sodemo", []); app.controller("sodemocontroller", sodemocontroller); sodemocontroller.$inject = ['$scope', '$document']; function sodemocontroller($scope, $document) { var vm = { data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] }; $scope.vm = vm; $('.table-container').on('scroll', onscroll); return; /////////// implemenation //////// function onscroll() { var translate = "translate(0," + this.scrolltop + "px)"; $("table thead th:not(.pinned)").css('transform', translate); translate = "translate(" + this.scrollleft + "px,0)"; $("table tbody .pinned").css('transform', translate); translate = "translate(" + this.scrollleft + "px," + this.scrolltop + "px)"; $("table thead th.pinned").css('transform', translate); } } })();
.table-container { overflow: auto; height: 200px; width: 300px } table { table-layout: fixed; border-spacing: 0; } td { padding: 3px; white-space: nowrap; border-right: 1px solid #ccc; } th { background: #999; } th.pinned { background: #ccc; } td.pinned { background: #eee; } input { margin-top: 20px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script> <div class="sample" ng-app="sodemo" ng-controller="sodemocontroller"> <p>when scroll horizontally, header row scrolls on top of col0 , col1 instead of behind it.</p> <p>when scroll vertically, tbody cells render on top of col 0 , col 1 headers instead of behind it</p> <div class="table-container"> <table> <thead> <tr> <th class="pinned">col 0</th> <th class="pinned">col 1</th> <th>col 2</th> <th>col 3</th> <th>col 4</th> <th>col 5</th> <th>col 6</th> <th>col 7</th> <th>col 8</th> <th>col 9</th> </tr> </thead> <tbody> <tr ng-repeat="item in vm.data"> <td class="pinned">data {{item}}</td> <td class="pinned">data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> </tr> </tbody> </table> </div> </div>
i think still z-index issue.
thanks @sascha10000 got me thinking missing. if add position: relative
th.pinned
class in css , add positive z-index
. (i.e. z-index:20
) appears work.
(function() { var app = angular.module("sodemo", []); app.controller("sodemocontroller", sodemocontroller); sodemocontroller.$inject = ['$scope', '$document']; function sodemocontroller($scope, $document) { var vm = { data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] }; $scope.vm = vm; $('.table-container').on('scroll', onscroll); return; /////////// implemenation //////// function onscroll() { var translate = "translate(0," + this.scrolltop + "px)"; $("table thead th:not(.pinned)").css('transform', translate); translate = "translate(" + this.scrollleft + "px,0)"; $("table tbody .pinned").css('transform', translate); translate = "translate(" + this.scrollleft + "px," + this.scrolltop + "px)"; $("table thead th.pinned").css('transform', translate); } } })();
.table-container { overflow: auto; height: 200px; width: 300px } table { table-layout: fixed; border-width: 0; border-spacing: 0; } td { padding: 3px; white-space: nowrap; border-right: 1px solid #ccc; } th { background: #999; } th.pinned { position: relative; /**** <=== added ****/ z-index: 20; /**** <=== added ****/ background: #ccc; } td.pinned { background: #eee; } input { margin-top: 20px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script> <div class="sample" ng-app="sodemo" ng-controller="sodemocontroller"> <p>when scroll horizontally, header row scrolls on top of col0 , col1 instead of behind it.</p> <p>when scroll vertically, tbody cells render on top of col 0 , col 1 headers instead of behind it</p> <div class="table-container"> <table> <thead> <tr> <th class="pinned">col 0</th> <th class="pinned">col 1</th> <th>col 2</th> <th>col 3</th> <th>col 4</th> <th>col 5</th> <th>col 6</th> <th>col 7</th> <th>col 8</th> <th>col 9</th> </tr> </thead> <tbody> <tr ng-repeat="item in vm.data"> <td class="pinned">data {{item}}</td> <td class="pinned">data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> <td>data {{item}}</td> </tr> </tbody> </table> </div> </div>
Comments
Post a Comment