11

Is it possible to add a floating horizontal scrollbar to a mat-table in Angular 7 without JQuery or any other additional plugins?

I have a mat-table that shows 6 columns but also can dynamically add 100+ columns with the push of a button.
But then the layout breaks.

HTML-Part:

<button (click)="showLess()" mat-stroked-button class="show-button">Show Less</button>
<button (click)="showMore()" mat-stroked-button class="show-button">Show More</button>

<div class="component data component-card">
<mat-card *ngIf="dataSource?.filteredData" class="mat-card">
    <mat-paginator [length]="length" [pageSize]="100" [pageSizeOptions]="[100, 250, 500, 1000, 2000]" showFirstLastButtons> </mat-paginator>
    <mat-table [dataSource]="dataSource" matSort class="table">
        <ng-container class="container" *ngFor="let displayedColumn of displayedColumns" matColumnDef="{{ displayedColumn }}">
            <mat-header-cell class="header-cell" *matHeaderCellDef >
                <span mat-sort-header class="sort-header">{{ displayedColumn | uppercase }}</span>
                <input class="table-input" matInput (keyup)="applyFilter($event.target.value)" (focus)="setupFilter(displayedColumn)" placeholder="Filter"/>
            </mat-header-cell>
            <mat-cell class="cell" *matCellDef="let item">{{ item[displayedColumn] }}</mat-cell>
        </ng-container>
        <mat-header-row class="header-row" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
        <mat-row class="row" *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>
</mat-card>

CSS-Part:

.data {
    display: block;
    width: 95vw;
    overflow: auto;

    .table {
        width: 100vw;
        max-width: 100%;
        overflow: auto;
        margin-bottom: 10px;
        display: table;
        border-collapse: collapse;
        margin: 0px;
        background-color: rgb(238, 238, 238);
}
    .row,
    .header-row {
        display: table-row;
        min-height: 36px !important;
}
    .cell,
    .header-cell {
        word-wrap: initial;
        display: table-cell;
        padding: 0px 5px;
        line-break: unset;
        width: fit-content;
        white-space: nowrap;
        overflow: hidden;
        vertical-align: middle;
        text-align: center;
}
    .header-row,
    .header-cell {
        margin: 0 auto;
        min-height: 100px !important;
        text-align: center;
        vertical-align: middle;
        align-self: center;
}
    .sort-header {
        display: flex;
        align-content: center;
        text-align: center;
        justify-content: center;
        font-size: 12pt;
}
    .header-cell {
        font-weight: bold;
    }
}

.mat-card {
    min-width: max-content;
    max-width: max-content;
}

If the overflows are both active then I have to scroll down to be able to scroll horizontally but the layout stays as it should. Only the mat-table and the div around it it will be scrolled and the elements above the mat-table (search fields etc.) are staying where they should. Everything stays in the middle of the screen.

If I deactivate the overflow from the div in the ".data" then the normal browser scrollbar appears and I don't have to scroll down anymore. But the mat-table expands the screen to the right on scrolling and the search fields above will stay on the left when scrolling horizontally which for me breaks the layout.

What I need would be a combination of both scrollbars which would be a floating scrollbar in my eyes. I would only scroll the mat-table but the rest stays in place.

Is there a way to accomplish that natively with CSS or Angular?

Demo: https://stackblitz.com/edit/angular-elm867?file=src%2Fapp%2Fapp.component.scss

If you click on Show More just see how the buttons behave when scroll after commentating "overflow: auto" in and out in the ".data".

Here's an image on how the table scrollbar should replace the normal scrollbar: enter image description here

suckerp
  • 310
  • 1
  • 4
  • 11
  • 2
    Please create a stackblitz demo for the problem – Abhishek Kumar Mar 25 '19 at 09:44
  • https://stackblitz.com/edit/angular-elm867?file=src%2Fapp%2Fapp.component.scss If you click on Show More just see how the buttons behave when scroll after commentating "overflow: auto" in and out in the ".data". – suckerp Mar 25 '19 at 10:22
  • If this is what you need ? See : https://stackblitz.com/edit/angular-horizontal-alignment?file=src/app/app.component.scss , or suggest, i can change accordingly – Abhishek Kumar Mar 25 '19 at 10:42
  • Thanks. The outer scrollbar should behave like the inner one and only one scrollbar should be visible. The inner scrollbar is the one from ".data". Not sure if the "overflow" from ".table" has an effect. I populated the table with more data to make it clearer. When scrolling horizontally the table data / headers should move left / right and the buttons in this example need to stay always visible. Both happens with "overflow" activated in ".data". But the scrollbar should be at the bottom of the browser and not at the end of the table. – suckerp Mar 25 '19 at 11:48
  • Also it would be great if the paginator could float along with the scrolling always staying on the right of the actual view. – suckerp Mar 25 '19 at 11:49
  • i have added an answer with removed horizontal scroll, please see the example in full window to see the proper working. Also suggest some changes to achieve the desired solution. – Abhishek Kumar Mar 25 '19 at 11:59
  • Does this answer your question? [Angular Material table Sizing/Scroll](https://stackoverflow.com/questions/50824617/angular-material-table-sizing-scroll) – rofrol Apr 25 '23 at 10:07

5 Answers5

22

I hope this will be helpfull for others to add Horizontal Scrolling to mat-table and column width according to cell content.

.mat-table {
      overflow-x: scroll;
    }

.mat-cell,
.mat-header-cell {
    word-wrap: initial;
    display: table-cell;
    padding: 0px 10px;
    line-break: unset;
    width: 100%;
    white-space: nowrap;
    overflow: hidden;
    vertical-align: middle;
}
.mat-row,
.mat-header-row {
    display: table-row;
}
CornelC
  • 4,974
  • 1
  • 21
  • 28
Muhammad Sohail
  • 828
  • 9
  • 18
3

i just add this css codes:

.mat-table {
    overflow-x: scroll;
}

.mat-row,
.mat-header-row {
    min-width: 800px;
}
amin arghavani
  • 1,883
  • 14
  • 21
1

in your existing stackblitz, Need one change to accomplish this...

In SCSS, define the class as: mat-paginator{width:97vw;}

Akber Iqbal
  • 14,487
  • 12
  • 48
  • 70
1

Add the following to styles.css to remove the horizontal scroll bar

html,
body {
  margin: 0 !important;
  padding: 0 !important;
}

Also add to bring horizontal scroll in .table if extra columns are overflowed.

.mat-card {
    min-width: 100% !important;
    max-width: 100% !important;
}
.table {
  display: block !important;
}

Stackblitz Demo with adjusted table data after dynamic column addition


Update 1 :

Fixed the max-height for the container div .data for fixing the horizontal scroll bar in the container.

.data {
  max-height: 500px;
  overflow: auto;
}

Demo with Fixed Max Height on Outer Container for fixing scrolls

Abhishek Kumar
  • 2,501
  • 10
  • 25
  • Unfortunately it's not working the way I meant it to work. For 6 columns it's good, but imagine table with 20, 30, 50 or even more columns and 1.000+ entires then you'd still need to scroll down to get the horizontal scrollbar. I can completely deactivate the normal scrollbar by adding "overflow-x: hidden" to .body, .main in scss. And what needs to happen now is that the scrollbar from the bottom of the table needs to become the new browser scrollbar. It might sound very complicated, I assume. I added additonal columns and data to illustrate this. – suckerp Mar 25 '19 at 12:46
  • @suckerp i have implemented the scenario, please see this updated stackblitz as a reference to achieve your desired result. – Abhishek Kumar Mar 26 '19 at 05:43
0

This might help:

<mat-card>
 <mat-card-content style="width:100vw"></mat-card-content>
</mat-card>