Search code examples
angular-materialtext-alignangular-material-table

How to (right/left/center) align individual column headers in mat-table with mat-sort-header?


I'm using Angular 16 with Angular Material 16, and I have designed a table with sortable columns following the documentation here. Certain columns contain numerical data and I'd like to right-align them. There are other columns I might like to center-align. I'm not looking to apply the same horizontal alignment to all the columns.

Angular Material automatically generates CSS classes for each column like .mat-column-<column-name>, so you can style all the cells in a column. This works to right-align the numbers in column foo:

.mat-column-foo {
    text-align: right;
}

It even works on the TH header cells for that column, at first. However, after I added sorting to my column, using mat-sort-header, the newly generated header is aligned left by default. This is a typical column definition in my HTML:

<ng-container matColumnDef="foo">
    <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by Foo">FOO</th>
    <th mat-cell *matCellDef="let element">{{element.foo}}</td>
</ng-container>

How can I right-align the sortable header, or center-align another such header?

Other questions I looked at:

  • 46154838 about ways to center-align all the headers.
  • 59418930 is about center-aligning only, and doesn't have an answer that applies to the mat-sort-header condition.

Solution

  • I found a partial answer from TotallyNewb on question 76505146. He indicates that "since this happens inside a new component injected through a directive, [a CSS solution] needs to happen in global styles". Thus, to center-align a column heading, he creates a new style in the global styles.scss, and applies it to the TH in the component HTML.

    Expanding on that answer to add an option for right-align, here is what I added to my global styles.scss:

    .centered-sorted-header {  
      .mat-sort-header-container {
        justify-content: center;
      }
    }
    .right-aligned-sorted-header {  
      .mat-sort-header-container {
        justify-content: end;
      }
    }
    

    Then, in my component's HTML, I can define a right-aligned and a centered column like this:

    <ng-container matColumnDef="foo">
        <th class="centered-sorted-header" mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by Foo">Foo</th>
        <th mat-cell *matCellDef="let element">{{element.foo}}</td>
    </ng-container>
    
    <ng-container matColumnDef="bar">
        <th class="right-aligned-sorted-header" mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by Foo">Bar</th>
        <th mat-cell *matCellDef="let element">{{element.bar}}</td>
    </ng-container>
    

    Meanwhile, this CSS in the component SCSS file aligns the table elements (other than the header):

    .mat-column-foo {
        text-align: center;
    }
    .mat-column-bar {
        text-align: right;
    }
    

    This works. If there's a way to do it without affecting global styles, so all the code changes stay in the component, that would be preferred.