I have a simple Bootstrap table with a lot of rows. Is there a way to make the table header be fixed when scrolling the window, but have the width of each column header to equal the width of the row with the most text. Because when setting table header position to fixed, then the header doesn't change its width based off the content. In other words set width of each column dependent on widest value (be that title in the header or value in a cell) in the column. Is there a way to put such calculations on the header column width ? I cant think of any other way to do this. I am using angular.
Here's a jsfiddle of what I've tried when setting position of header row to fixed : JsFiddle As you can see now the columns don't align with the appropriate columns in the body. I need them to be aligned, but without setting a fixed width for every column, since I do not know how long the data I'm getting will be.
.table-bordered tr {
position: fixed;
z-index: 1;
top: 50px;
background: #fff;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<div class="col-md-12 tableDiv">
<table class="table table-striped">
<thead class="table-bordered">
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
<th>Column5</th>
<th>Column6</th>
</tr>
</thead>
<tbody>
<tr>
<td> FIRST</td>
<td>asdasdfasf</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td> asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td> asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
If you don't care about the performance and you can live without borders in the header (because the borders will not get the CSS
transform), there is a solution using CSS3
transforms. The technique is to take the scroll of the window and apply a transform to the header with the same value. In this way, the header is not fixed and it maintains its original widths:
let header = document.querySelector(".table-bordered");
let body = document.body;
function setTranslate (element, value) {
let style = `translateY(${value}px)`;
element.style.oTransform = style;
element.style.MozTransform = style;
element.style.WebkitTransform = style;
element.style.transform = style;
}
window.onscroll = () => {
setTranslate(header, window.scrollY);
};
The bad part about this solution is that you need to update the styles of the header in every scroll event, so, the performance will not be well enough. Another solution is to build two different tables, one for the header and another for the body and a generic function that set the widths of the header taking into account the widths of the body. In this way, you can set the position
property of the table in fixed
and you could call this function in every resize of the window or in every moment that you need to refresh the sizes of the table. Take a look at the next snippet:
let header = document.querySelector(".table-header");
let body = document.querySelector(".table-body");
let htds = header.querySelectorAll("th");
let btds = body.querySelectorAll("tbody tr:first-child td");
function fixHeaderWidths() {
header.style.width = `${body.offsetWidth}px`;
Array.prototype.forEach.call(htds, (td, index) => {
td.style.width = `${btds[index].offsetWidth}px`;
});
body.style.top = "";
let top = (header.getBoundingClientRect()).bottom - (btds[0].getBoundingClientRect()).top;
body.style.top = `${top}px`;
}
fixHeaderWidths();
window.onresize = fixHeaderWidths;
.table-header {
background: white;
position: fixed;
table-layout: fixed;
z-index: 1;
}
.table-body {
position: relative;
}
.table-body thead {
visibility: hidden;
}
.tableDiv {
margin-top: 40px
}
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/flatly/bootstrap.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet" />
<div class="col-md-12 tableDiv">
<table class="table-header table table-stripedcf table-bordered">
<thead>
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
<th>Column5</th>
<th>Column6</th>
</tr>
</thead>
</table>
<table class="table-body table table-stripedcf table-bordered">
<thead>
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
<th>Column5</th>
<th>Column6</th>
</tr>
</thead>
<tbody>
<tr>
<td>FIRST</td>
<td>asda sdfasf</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
<tr>
<td>asdf</td>
<td>asdfa</td>
<td>fsdf</td>
<td>sdfsfd</td>
<td>sdfs</td>
<td>fsdfsdf</td>
</tr>
</tbody>
</table>
</div>
If you don't want to use
jQuery
, don't use theBootstrap
script file (I've seen that you have included it in yourjsFiddle
) because it requiresjQuery
to work. But you can use to replace it something like this.