Avoid duplicate styles in Angular Material theme
Asked Answered
G

4

8

I have a styles.theme.scss that looks like the following.

@media (prefers-color-scheme: dark) {
  @include example-theme($dark-theme);
}

@media (prefers-color-scheme: light) {
  @include example-theme($light-theme);
}

[data-theme="dark-theme"] {
  @include example-theme($dark-theme);
}

[data-theme="light-theme"] {
  @include example-theme($light-theme);
}

The goal is to use the prefers-color-scheme if that is configured by the user agent, but override it if the user has configured it on the website.

The current SCSS causes the following warning, however:

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()
    stdin 29:3                                           example-theme()
    stdin 57:3                                           root stylesheet

I've checked the provided documentation, but it doesn't appear to cover this case, and I'm unsure on how to better structure this to avoid duplicating the styles.

The only solution I think would work is to detect the preference with JavaScript, and then set the data-theme attribute if a theme isn't configured in the application.

Is there a better solution than this?

What I've tried:

  • To see if I could string a media query and selector together like [data-theme="dark-theme"], @media (prefers-color-scheme: dark), which I don't believe is possible.
  • If I can use SASS @if and @else to check if the data-theme selectors match any elements, else include the @media queries.
Gourmandise answered 8/9, 2020 at 3:3 Comment(1)
The best answer doens't support the prefers-color-scheme. Did you get it to work with you sugestion of detecting with JavaScript? I mean, if you have to use the media-query, you're probably using the include inside the media, rigth? If you use include twice (dark-theme and media), even if it's all-component-colors, it'ill give you the warning.Teeming
N
12

You should include mat.all-component-colors instead of mat.all-component-themes

Example: below is wrong

// Generates styles for all systems configured in the theme. In this case, color styles
// and default density styles are generated. Density is in themes by default.
@include mat.all-component-themes($light-theme);

.dark-theme {
  // Generates styles for all systems configured in the theme. In this case, color styles
  // and the default density styles are generated. **Note** that this is a problem because it
  // means that density styles are generated *again*, even though only the color should change.
  @include mat.all-component-themes($dark-theme);
}

Use this instead:

@use '@angular/material' as mat;

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

.dark-theme {
  // This mixin only generates the color styles now.
  @include mat.all-component-colors($dark-theme);
}

For more information, Official Docs

Neurovascular answered 21/2, 2022 at 11:44 Comment(0)
A
2

I also find my self fighting same issue today. The problem with your styling is you have two theme light and dark and in

@include angular-material-theme('Your-Theme');

you have to provide a theme ( light or dark).

so you should overwrite only one of theme because other is already included so overwrite media query dark if you provided light one or vice versa.

here is my code sample

@import "~@angular/material/theming";
@include mat-core();

$kyc-web-primary: mat-palette($mat-pink);
$kyc-web-accent: mat-palette($mat-pink, A200, A100, A400);
$kyc-web-warn: mat-palette($mat-red);

$kyc-web-theme-light: mat-light-theme(
  (
    color: (
      primary: $kyc-web-primary,
      accent: $kyc-web-accent,
      warn: $kyc-web-warn,
    ),
  )
);

$kyc-web-theme-dark: mat-dark-theme(
  (
    color: (
      primary: $kyc-web-primary,
      accent: $kyc-web-accent,
      warn: $kyc-web-warn,
    ),
  )
);

@include angular-material-theme($kyc-web-theme-dark);


@media (prefers-color-scheme: light) {
  @include angular-material-color($kyc-web-theme-light);
}
Adcock answered 15/9, 2020 at 18:48 Comment(0)
E
1

mat.$theme-ignore-duplication-warnings: true;

Elamitic answered 2/9, 2021 at 14:26 Comment(3)
This is the correct answer, if you intend to have multiple themes (e.g. light and dark) inside the app. See: github.com/angular/components/blob/master/guides/…Borchers
What's the .scss equivalent to this? I get error: "identifier expectedscss(css-identifierexpected)"Evania
@Evania I'm getting exactly the same error, would like to know the solution to this...Vanzant
S
-1

If you use scss you can use this : $mat-theme-ignore-duplication-warnings: true; to avoid warning if you intend to have multiple themes

Smyrna answered 23/1 at 12:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.