How to generate the same color styles not multiple times in angular?

In Angular, I generate a custom theme file, a root styles file, and all my components have their own custom styles file. However, since I updated to Version 10, my terminal is spammed by the warning

WARNING: The same color styles are generated multiple times. Read more about how style duplication can be avoided in a dedicated guide. https://github.com/angular/components/blob/master/guides/duplicate-theming-styles.md
    node_modules/@angular/material/_theming.scss 1648:7  -mat-check-duplicate-theme-styles()
    node_modules/@angular/material/_theming.scss 7010:3  angular-material-theme()
    node_modules/@angular/material/_theming.scss 7061:3  angular-material-color()
    src/_custom_theme.scss 242:3                         @import
    stdin 2:9        

Following the guide, I could reduce this error to a minimum of four arrivals. This error lists my custom_theme file and @angular/material from my node_modules. I really wonder what I'm doing wrong leading to this error. At line 242 of my custom_theme I am generating my dark theme .custom-dark-theme { @include angular-material-color($app-theme-dark); }


Solution 1:

The general thing to do is to avoid your components sccs @import-ing a file which itself @includes one of the material core mixins. So you could define the theme and maybe some sharable theme constants/mixins in a partial, then create the styles in the global style which imports the theme definition. More explicitly:

  • Create a file something like _my-theme.scss, the leading underscore makes it a sass partial.
  • In this file, only define the theme by calling material’s material-light-theme function. Note that this is just a function, which is just creating a big Sass map that the rest of the material library uses to actually generate styles. Itself it does not “generate” styles, like the mixins do.
  • In the global/root style file, import 'my-theme', and then @include The color/styles mixin.
  • In your component files, only import from my custom theme partial and not from the root file

However, with the more recent versions of Sass and Angular 12, the better way to do this is instead of using @import, you use the @use syntax which better handles “sharing” common code in those partial files. Simple example/starter-code

_my-theme.scss

@use "~@angular/material" as mat;

$my-theme-dark: mat.define-dark-theme(
  // stuff here
);

Root styles.scss


@use "~@angular/material" as mat;
@use './my-theme' as my-theme;

@include mat.core()

// general style defaults

.app-dark {
  @include mat.all-component-colors(my-theme.$my-theme-dark);
}

some-component.scss


@use "~@angular/material" as mat;
@use 'my-theme' as my-theme;

// do anything with mat and your definitions from my-theme