I am trying to fix the column headers so that I can scroll horizontally and yet see the headers. I have tried the following but doesn't seem to work. If you see in the screenshots If I move the screen up or down, the headers dont seem to stay in one place and there is improper overlap. The first td is always hidden behind the th.
screenshot 1
screenshot 2
th:first-child {
position: fixed;
}
th {
position: fixed;
}
.fixed-side {
border:1px solid #000;
background:#eee;
visibility:visible;
}
CSS
<style>
th,
td {
padding: 7px;
min-width: 300px;
max-width: 300px;
}
/* th:first-child {
position: fixed;
} */
th {
position: fixed;
}
.fundClassesTable {
table-layout: fixed;
}
.cellbgcolor {
color: transparent;
}
.btn {}
.tableItem {
text-align: left;
border-left: solid 1px lightgrey;
border-top: solid 1px lightgrey;
border-right: solid 1px lightgrey;
border-bottom: solid 1px lightgrey;
}
.rowItem:hover {
background-color: #f5f7f7;
}
label {
margin-left: 0.5rem;
vertical-align: middle
}
.panel-heading {
color: black;
border-color: #ddd;
overflow: hidden;
padding-top: 5px !important;
padding-bottom: 5px !important;
}
.panel-heading .left-label {
display: inline-block;
padding-top: 5px !important;
}
.scrollClass {
overflow-x: scroll;
display: grid;
}
.panel-heading label {
margin-bottom: 0px !important;
}
#FundClass tr:hover {
background-color: #ECF0F1;
}
.headcol {
position: absolute;
min-width: 300px;
max-width: 300px;
width: 5em;
left: 0;
top: auto;
border-top-width: 1px;
/*only relevant for first row*/
margin-top: -1px;
/*compensate for top border*/
}
.headcol:before {
content: 'Row ';
}
.collapsed {
color: #d6630a;
font-size: 22px;
text-decoration: none;
font-weight: bold;
}
.expanded {
color: #d6630a;
font-size: 22px;
text-decoration: none;
font-weight: bold;
}
.fixed-side {
border:1px solid #000;
background:#eee;
visibility:visible;
}
</style>
HTML
<div class="card">
<div class="card-header panel-heading">
<span class="left-label" style="font-size: 18px; font-weight: bold; ">Fund Classes</span>
<a class="pull-right" [ngClass]="{'collapsed': !isExpanded, 'expanded': isExpanded }" data-toggle="collapse"
href="javascript:void(0);" (click)="expand()" role="button" [attr.aria-expanded]="isExpanded"
aria-controls="fundClass"> {{ isExpanded ? '-' : '+' }}
</a>
<div *ngIf="CanEdit" class="pull-right"
style="padding-right:10px; display: inline-block; vertical-align:middle">
<button style="text-align: center; vertical-align:middle" class="btn btn-default pull-right"
(click)="openFundClassModal()"> <i data-bind="visible: true" class="fa fa-plus-square"></i> Add
Class</button>
</div>
<div class="pull-right" style="padding-right:10px; display: inline-block; vertical-align:middle">
<label style="text-align: center; vertical-align:middle" class="btn btn-primary"
[ngClass]="{'btn-primary': InvestedOnly, 'btn-default': !InvestedOnly }"><input type="checkbox"
(click)="isInvestedSelected($event)" checked="checked" [(ngModel)]="InvestedOnly" class="hidden"
for="chkInvested" />Invested Only</label>
</div>
</div>
<div *ngIf="!FundClasses || !FundClasses.FundDetailsViewModel" style="padding-top:10px">
<div class="alert alert-warning" style="text-align:center" role="alert">
Loading... Please Wait
</div>
</div>
<div [ngClass]="{'show': isExpanded}" id="fundClass" class="collapse" role="tabpanel" aria-labelledby="fundClass_heading"
data-parent="#fundClass" [attr.aria-expanded]="isExpanded">
<div class="card-body scrollClass" *ngIf="FundClasses && FundClasses.FundDetailsViewModel">
<table id="FundClass" class="fundClassesTable table-striped">
<!-- *ngIf="c != 'Buttons1' && !CanEdit" -->
<tr *ngFor="let c of FundClasses.FundClassColumnNames">
<th class="fixed-side" scope="col" [ngClass]="c != 'Buttons1'? 'tableItem bold' : 'tableItem cellbgcolor'"> {{ c }}</th>
<ng-container *ngFor="let fundClass of FundClasses.FundDetailsViewModel let i=index">
<ng-container *ngFor="let f of fundClass['FundClassDetailsViewModel'] | keyvalue">
<td class="tableItem" style="font-weight: bold" *ngIf="c == 'Fund Name'">
{{ f.value.FundName}}
</td>
<td [attr.id]="'f.value.Id'" class="tableItem"
*ngIf="!EditMode[f.value.Id] && c == 'Accounting Class Name'">{{ f.value.Description}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Accounting Class Name'"
class="tableItem">
<input kendoTextBox [(ngModel)]="f.value.Description"
style="width: 284px; height: 29.5px;" />
</td>
<td class="tableItem" *ngIf="c == 'Class ID'">{{f.value.Id}}</td>
<td *ngIf="EditMode[f.value.Id] && c == 'Legal Fund Class'" class="tableItem">
<kendo-dropdownlist [(ngModel)]="f.value.LegalFundClassId"
class="form-control form-control-sm " [data]="fundClass.PrimaryLegalFundClasses"
[filterable]="false" textField="Description" [valuePrimitive]="true"
valueField="Id">
</kendo-dropdownlist>
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Legal Fund Class'"
class="tableItem">
{{ f.value.LegalFundClassName}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Inception Date'"
class="tableItem">
<kendo-datepicker [format]="'MMM dd, yyyy'" [(ngModel)]="f.value.InceptionDate"
class="form-control form-control-sm">
</kendo-datepicker>
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Inception Date'"
class="tableItem">
{{ f.value.InceptionDate | date:"'MMM dd, yyyy"}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Invested Amount'"
class="tableItem">
<input kendoTextBox [(ngModel)]="f.value.InvestedAmount"
style="width: 284px; height: 29.5px;" />
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Invested Amount'"
class="tableItem">
{{ f.value.InvestedAmount | number : '.2-2'}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Vehicle Type'"
class="tableItem">
<kendo-dropdownlist [(ngModel)]="f.value.VehicleTypeId"
class="form-control form-control-sm " [data]="FundClasses.VehicleTypes"
[filterable]="false" textField="Name" [valuePrimitive]="true" valueField="Id">
</kendo-dropdownlist>
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Vehicle Type'"
class="tableItem">
{{ f.value.VehicleTypeName}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Closure Status'"
class="tableItem">
<kendo-dropdownlist [(ngModel)]="f.value.ClosureStatusId"
class="form-control form-control-sm" [data]="FundClasses.ClosureStatuses"
[filterable]="false" textField="Name" [valuePrimitive]="true" valueField="Id">
</kendo-dropdownlist>
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Closure Status'"
class="tableItem">
{{ f.value.ClosureStatusName}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Is Side Pocket?'"
class="tableItem">
<input type="checkbox" value="{{f.value.IsSidePocket}}" id="chkSidePocket"
[(ngModel)]="f.value.IsSidePocket" style="width: 13px; height: 13px;" />
<label for="chk">Yes</label>
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Is Side Pocket?'"
class="tableItem">
{{ f.value.IsSidePocket == true ? 'Yes' : 'No'}}
</td>
<td [attr.id]="'f.value.Id'" *ngIf="EditMode[f.value.Id] && c == 'Is Thematic?'"
class="tableItem">
<input type="checkbox" value="{{f.value.IsThematic}}" style="width: 13px; height: 13px;"
[(ngModel)]="f.value.IsThematic" />
<label for="chkThematic">Yes</label>
</td>
<td [attr.id]="'f.value.Id'" *ngIf="!EditMode[f.value.Id] && c == 'Is Thematic?'"
class="tableItem">
{{ f.value.IsThematic == true ? 'Yes' : 'No'}}
</td>
<td class="tableItem" *ngIf="c == 'Buttons1' && CanEdit">
<button *ngIf="!EditMode[f.value.Id]" type="button"
class="btn btn-primary btn mr-1 "
(click)="buttonClicked(f.value.Id)">Edit</button>
<button *ngIf="EditMode[f.value.Id]" type="button"
class="btn btn-primary btn mr-1"
(click)="Update(f.value.Id)">Save</button>
<button *ngIf="EditMode[f.value.Id]" type="button"
class="btn btn-primary btn mr-1"
(click)="Delete(f.value.Id)">Delete</button>
<button *ngIf="EditMode[f.value.Id]" type="button"
class="btn btn-primary btn mr-1"
(click)="buttonClicked(f.value.Id)">Cancel</button>
</td>
</ng-container>
</ng-container>
</tr>
</table>
</div>
</div>
</div>
Update 1
After trying darthnach's solution, have a small issue while scrolling. I can see the contents in the margin
css
th {
padding: 7px;
position: sticky;
left:0;
min-width: 300px;
background-color:#f5f7f7;
}
Screenshot 1
Screenshot 2
Here is the stackblitz
stackblitz.com/edit/angular-d1mzew
Update 2
Fix for addressing the border issue while scrolling but text visibility persist while scrolling
By setting postion: sticky and top: 0, we can create a fixed header on a scroll in HTML tables.
If your header row locates on the top of the worksheet, please click View > Freeze Panes > Freeze Top Rows directly. See screenshot. Now the header row is frozen. And it will follow the worksheet up and down while scrolling the worksheet.
Horizontal scrolling can be achieved by clicking and dragging a horizontal scroll bar, swiping sideways on a desktop trackpad or trackpad mouse, pressing left and right arrow keys, or swiping sideways with one's finger on a touchscreen.
Set the overflow-y: hidden; and overflow-x: auto; that will automatically hide the vertical scroll bar and present only the horizontal scrollbar. The white-space: nowrap; property is used to wrap text in a single line. Here the scroll div will be horizontally scrollable.
Building upon @Sethuraman 's answer, if you replace padding
with margin
and then put a border on the div wrapping table, it might solve your problem of border (not sure if this is what you're trying to address)
You can try below change:
.card-body {
flex: 1 1 auto;
padding: 0;
margin: 10px 0;
/* border: 1px solid lightgray; */ <-- You can add or remove this based on your need
}
This is before and after modifying the above class.
Furthermore, you can remove the border spacing to avoid 2px scroll gap on the th
elements while scrolling the content towards left.
.fundClassesTable[_ngcontent-xcq-c0] {
table-layout: fixed;
border-spacing: 0;
}
Please let me know if this helps or you are looking for something else.
In .card-body
instead of padding try margin it may solve your problem, i have wored on stackblitz -- https://stackblitz.com/edit/angular-d1mzew
.card-body {
flex: 1 1 auto;
/* padding: 10px; */
margin: 10px;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With