table with sticky header and horizontal scroll
As per the MDN documentation:
a sticky element "sticks" to its nearest ancestor that has a "scrolling mechanism" (created when
overflow
ishidden
,scroll
,auto
, oroverlay
), even if that ancestor isn't the nearest actually scrolling ancestor.
There's an active GitHub issue discussing this on the W3C repo, which has been running since 2017. There have been various workarounds suggested, but they all seem to rely on adding a fixed height to the table / table container, or using Javascript as in this answer.
At least for the moment, this is not something that's supported natively.
Fixed table header with horizontal AND vertical scrolling body
You are cloning the table for fix header, better you can direct fix the header of original table which will results the same.
Element with position:fixed
changes the width with respect to viewport, which results width gets change on scrolling as you can check here https://jsfiddle.net/chourasiapawankumar/vg7q3tyc/19
Approach:1
instead of
position:fixed
userelative
inth
and it is working with your parentdiv
which hasmin-height:100px
.https://jsfiddle.net/chourasiapawankumar/krw0qpbL/62/
Approach:2
You can see both horizontal and vertical scroll bar at a time on removing
min-height
of parent div which I have commented in the below fiddle.https://jsfiddle.net/chourasiapawankumar/vg7q3tyc/33/
Extra horizontal scroll bar on fixed-header HTML table?
The scrollbar you are talking about is being added to the tbody
element. By turning tbody
into a block, overscroll:auto
is being added by default, even though you only include overflow-y
in your CSS:
thead tr, tbody {
display: block;
}
tbody {
height: 300px;
overflow-y: auto;
}
Partial Solution (works when there is no horizontal overflow)
Adding overflow-y:hidden
to tbody
will remove the second horizontal scrollbar, and this works when there is no horizontal overflow. However if there is, the vertical scrollbar gets "stuck" to the column positioned at the max-width and scrolls with the tbody, as you can see here:
table {
table-layout: fixed;
width: 100%;
}
thead tr, tbody {
display: block;
}
tbody {
height: 300px;
overflow-y: auto;
overflow-x: hidden;
}
th, td {
width: 100px;
min-width: 100px;
}
<html>
<div style="max-width: 500px; overflow-y: auto;">
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
<th>Column 5</th>
<th>Column 6</th>
<th>Column 7</th>
<th>Column 8</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
<tr>
<td>Data1</td><td>Data2</td><td>Data3</td><td>Data4</td>
<td>Data5</td><td>Data6</td><td>Data7</td><td>Data8</td>
</tr>
</tbody>
</table>
</div>
</html>
Mat Table with sticky header and Horizontal ,vertical scroll bar
You can set the width and height to the div container wrap around the mat-table. On stylesheet, you can apply something like this:
.example-container {
width: 100%;
height: calc(100vh - 32px);
overflow: auto;
}
Example: https://stackblitz.com/edit/angular-hdg9xh-uxkaeh
Table with horizontal and vertical scroll with fixed header
There's a simple CSS solution to fix rows(headers) and columns in a table.
th {
position: sticky:
top: 0;
}
The above snippet will fix the header to the top. Then it's just a matter of adding a simple overflow to the parent container of the table. You can find a simple example below -
.table-container { overflow: auto; max-height: 160px; border: 1px solid red;}
th { position: sticky; top: 0; background: white;}
<div class="table-container"> <table> <thead> <tr> <th>Head 1</th> <th>Head 2</th> <th>Head 3</th> <th>Head 4</th> </tr> </thead> <tbody> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> <td>Data</td> </tr> </tbody> </table></div>
Fixed table header scroll both horizontal and vertical CSS ONLY
This is another one of those interesting challenges (like vertical centering) brought to us by the inaction of the W3C. Also like vertical centering, you can't put a fixed header on a table with a horizontal scrollbar using position: fixed;
on the thead
element. But you do have a couple of options.
Option 1 - Horizontal Scrolling (http://codepen.io/staypuftman/pen/JXbpvZ)
The key here is to reestablish your table layout as table-layout: fixed;
CSS-tricks has a good piece on this approach and then put a min-width
value on your container when you want the scrollbars to appear. This makes the table scrollable left to right and maintains the integrity of the column headers on smaller devices. But the header is not fixed.
Option 2 - Fixed Header (https://jsfiddle.net/dPixie/byB9d/3/light/)
Your code looked like a rip-off of this guy's work, so I thought I'd repost here to give him some credit. This approach creates a series of <div>
elements that mirror the contents of the <th>
elements and uses some VERY creative positioning techniques to get it all to work.
There is a much better run-down on Salzar design that shows some examples and explains in detail all the complicated maneuvers to get this right.
Horizontal scrollbar on table with sticky header
i have fixed this issue by providing the container a fixed max height, that way it will have the sticky header and scrolling as well.
.table-flow {
max-height: 555px;
overflow-x: scroll;
max-width: auto;
position: relative;
}
Table header fixed, scrollable body horizontal and vertical, variable cell width
Edited to handle the possibility of longer columns, as I didn't notice that prerequisite
Interesting problem!
You can achieve what you want with less CSS
and no jQuery
, if you are happy to set a fixed width for the columns:
If you ensure that your CSS is set so that the default column width is as long as is necessary for any table headers, then this solution should work:
CSS
table#vehicleTable {
position: relative;
display: block;
margin-left: 0px;
width: 400px;
height: 400px;
overflow-x: scroll;
overflow-y: hidden;
}
table#vehicleTable thead {
background-color: blue;
color: white;
}
table#vehicleTable tbody {
position: relative;
display: inline-block;
height: 345px; /*allowing for scrollbar and th height */
overflow-y: scroll;
}
table#vehicleTable td, table#vehicleTable th {
min-width: 100px; /*suitable width for all column headers in the example*/
}
/*Added this just to handle the 2nd column, which needs to be smaller, as per comments */
table#vehicleTable td:nth-of-type(2), table#vehicleTable th:nth-of-type(2) {
min-width: 30px;
text-align: center;
}
jQuery
$(window).on('load', function () {
$i = 0;
$("#vehicleTable tbody tr:first-of-type td").each(function()
{
$i++;
width = $(this).outerWidth();
$("#vehicleTable thead th:nth-of-type(" +$i+")").css({"min-width": width+"px"});
});
});
This will loop through the first row
of tbody
, and get the respective widths for each column. If you don't set a min-width
on them first, then any columns with data that is shorter than the column header will result in that column shrinking, while the header itself will still expand to fit its own content.
Also updated JSFiddle
Related Topics
How to Change the Time Format (12/24 Hours) of an <Input>
How to Display Image Encoded in Base64 Format in Angular 6
Div Elements Overlapping Each Other
How to Put Arrow Between Two Divs Using HTML and CSS
How to Create an HTML Table With a Fixed/Frozen Left Column and a Scrollable Body
Angular: *Ngif Tag on Input Element Causes It to Be Undefined. Cannot Read Value from Input Field
Understanding CSS Selector Priority/Specificity
How to Align 3 Divs (Left/Center/Right) Inside Another Div
Center and Bottom-Align Flex Items
How to Avoid Decimal Values in Input Type Number
Css Absolute Position With X Scrolling
Selecting an Option in a Dropdown List Using Request Parameters
How to Add HTML Line Break Within an Input Text Placeholder
Splitting the HTML Page Using Div
How to Toggle Mat-Expansion-Panel With Button Click