Fix broken Angular material legacy styles

January 12, 2023

With Angular version 15 many of the Angular material components have been refactored to use the Material Design Components for web (MDC). This change itself is awesome for all Angular folks because now the accessibility drastically improved and the components are closer to the official material specs.
However this also means that you need adapt and check your entire application because for some components even the API changed. To reduce the pain of upgrade (everything at once) Angular is providing the previous material components under a separate legacy import, e.g. import {MatSelectModule} from '@angular/material/select'; becomes import {MatLegacySelectModule as MatSelectModule} from '@angular/material/legacy-select'; (important: you really should use ng update then the cli will convert all imports automatically).

In my case I wanted to use the legacy components in all places to get the Angular upgrade done and tackle the new style components afterwards. After I upgraded everything with ng update nearly everything was broken and looked wrong.

Sample image of broken input field

I discovered that the way how you define a theme is now different for Angular Material 15 (See docs).

@use '@angular/material' as mat;

@include mat.core();

$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);

$my-theme: mat.define-light-theme((
 color: (
   primary: $my-primary,
   accent: $my-accent,
 typography: mat.define-typography-config(),
 density: 0,

@include mat.all-component-themes($my-theme);

But even with those changes the legacy components still look off.


We need to include another scss mixin for the core and legacy styles.

@use '@angular/material' as mat;

@include mat.core();
@include mat.legacy-core();
@include mat.all-component-themes($my-theme);
@include mat.all-legacy-component-themes($app-theme);

If you do not include the all-component-mixin you can also include individual legacy themes. They are always prefixed with legacy-

@include mat.button-theme($app-theme);
@include mat.legacy-button-theme($app-theme);

And now our styles look just like before Sample image of working input field

Personal Blog written by Nicolas Gehlert, software developer from Freiburg im Breisgau. Developer & Papa. Github | Twitter

Add a comment



April 09, 2023

Hi, That was great information for our project while upgrade material 14 to 15. We tried your solution but it didn’t work until some search and find it solution because of missing information. We should add this line

“@include mat.all-legacy-component-typographies();”



April 03, 2023

The very important part is missing, it makes work all component the are under mat-form-field @include mat.all-legacy-component-typographies();


March 10, 2023

Thanks so much <3


March 07, 2023

Many thanks from mee, too.


February 15, 2023

Hi, Thanks for the post! It saves my week! Everything works fine after that.

I clearly regret my migration. It was so simple before … Material 15 is just awfull (to stay polite) and unnecessarily complicated … especially with its default fixed font-sized inputs, making all components look enormous and ugly. Before it was herited from the context … it was so simple and intuitive. Now you need to code dozen of sass lines to get it worked (and need to know complex sass things to do a simple css changes)

In my opinion, they make a very wrong step and they gonna loose fans. Myself, I am thinking about quiting Material and finding something simpler to manipulate.

So thank you very much for this piece of code which works like a charm. For your information, I had to replace “$app-theme” by “$my-theme” in the last line.

++ Christophe

© 2023, Nicolas Gehlert
See Statistics for this blog