Angular Material - Global color variables

前端 未结 3 1068
温柔的废话
温柔的废话 2020-12-30 07:01

Looking at the Angular Material documentation, they recommend using a -theme file per component to manage applying any theme-related styles to a specific class.

相关标签:
3条回答
  • 2020-12-30 07:06

    I am working on a project where I used the Material 2 Themes and I used this approach where I use the class name and add colors class globally.

    This is what I did :

    FileName: mytheme-sidemenu.scss:

    // Import all the tools needed to customize the theme and extract parts of it
    @import "~@angular/material/theming";
    // Define a mixin that accepts a theme and outputs the color styles for the component.
    @mixin mytheme-sidemenu($theme) {
      // Extract whichever individual palettes you need from the theme.
      $primary: map-get($theme, primary);
      $accent: map-get(
        $theme,
        accent
      ); // Use mat-color to extract individual colors from a palette as necessary.
    
      .col-primary {
        color: mat-color($primary, 500) !important;
      }
      .col-accent {
        color: mat-color($accent, 300) !important;
      }
    }
    

    Here is my main theme file: mytheme-theme.scss:

    @import '~@angular/material/theming';
    @import './variables/helper.scss';
    @import './variables/spacemanager.scss';
    @import './mytheme-sidemenu.scss';
    
    // Primary theme
    @include mat-core();
    $mytheme-app-primary: mat-palette($mat-light-blue, 700, 600);
    $mytheme-app-accent: mat-palette($mat-pink, A200, 900, A100);
    $mytheme-app-warn: mat-palette($mat-deep-orange);
    $mytheme-app-theme: mat-light-theme($mytheme-app-primary, $mytheme-app-accent, $mytheme-app-warn);
    @include angular-material-theme($mytheme-app-theme);
    // Secondary Theme
    .mytheme-alt-theme {
        $mytheme-alt-primary: mat-palette($mat-blue-grey, 500);
        $mytheme-alt-accent: mat-palette($mat-pink, 500);
        $mytheme-alt-warn: mat-palette($mat-deep-orange);
        $mytheme-alt-theme: mat-light-theme($mytheme-alt-primary, $mytheme-alt-accent, $mytheme-alt-warn);
        @include angular-material-theme($mytheme-alt-theme);
    }
    // Using the $theme variable from the pre-built theme you can call the theming function
    @include mytheme-sidemenu($mytheme-app-theme);
    

    and in app.module.ts update this :

    export class AppModule {
      constructor(
        @Inject(OverlayContainer) private overlayContainer: OverlayContainer
      ) {
        this.overlayContainer
          .getContainerElement()
          .classList.add("mytheme-alt-theme"); // this for double theme add to the root css class
      }
    }
    
    0 讨论(0)
  • 2020-12-30 07:28

    I have defined primary,accent and warn colors as css custom variables in the styles.css file like so:

    @import "~@angular/material/theming";
    @include mat-core();
    
    $my-primary: mat-palette($mat-blue-grey);
    $my-accent: mat-palette($mat-amber, A200, A100, A400);
    $my-warn: mat-palette($mat-deep-orange);
    
    $my-2-primary: mat-palette($mat-pink, 400, 200, 600);
    $my-2-accent: mat-palette($mat-blue, A200, A100, A400);
    $my-2-warn: mat-palette($mat-deep-orange, 500, 300, 700);
    
    .dark-theme {
      $my-theme-dark: mat-dark-theme($my-primary, $my-accent, $my-warn);
      @include angular-material-theme($my-theme-dark);
      $primary: mat-color($my-primary);
      $accent: mat-color($my-accent);
      $warn: mat-color($my-warn);
      $fg_palette:map-get($my-theme-dark, foreground);
      $bg_palette:map-get($my-theme-dark, background);
      $fg:map-get($fg_palette, text);
      $bg:map-get($bg_palette, background);
    
      --primary: #{$primary};
      --accent: #{$accent};
      --warn: #{$warn};
      --fg: #{$fg};
      --bg: #{$bg};
    }
    
    .dark-theme-2 {
      $my-2-theme-dark: mat-dark-theme($my-2-primary, $my-2-accent, $my-2-warn);
      @include angular-material-theme($my-2-theme-dark);
      $primary: mat-color($my-2-primary);
      $accent: mat-color($my-2-accent);
      $warn: mat-color($my-2-warn);
      $fg_palette:map-get($my-2-theme-dark, foreground);
      $bg_palette:map-get($my-2-theme-dark, background);
      $fg:map-get($fg_palette, text);
      $bg:map-get($bg_palette, background);
    
      --primary: #{$primary};
      --accent: #{$accent};
      --warn: #{$warn};
      --fg: #{$fg};
      --bg: #{$bg};
    }
    

    And used these variables in any of my components like so:( in my-custom-component.scss)

    .some-class {
        color: var(--primary)
    }
    
    .another-class {
        background-color: var(--bg)
    }
    
    .yet-another-class {
        border-color: var(--accent)
    }
    

    By doing like this, i can change any value related to color in any component, because these variables are global (defined in styles.css) As i change theme, these colors also change according to new theme's color

    0 讨论(0)
  • 2020-12-30 07:30

    Why use @mixin?

    Just wanting to validate that the above is sound and that I'm not missing anything obvious that's going to cause pain down the track?

    The only thing, I can think of, is that you would miss the opportunity to use multiple themes in one application. With the approach from the Angular Material documentation, you would have a @mixin for each component, that you can @include multiple times with different $theme variables.

    Example from https://medium.com/@tomastrajan/the-complete-guide-to-angular-material-themes-4d165a9d24d1:

    .default-theme {
      @include angular-material-theme($theme);
      @include custom-component-theme($theme);
    }
    
    .light-theme {
      @include angular-material-theme($light-theme);
      @include custom-component-theme($light-theme);
    }
    

    This wouldn't work, if you import colors as scss-variables into your components and use it there.

    Separate file for colors

    The other tricky part is how to actually define these in a separate colors file efficiently given the file will need access to the theme data.

    This is actually pretty straight forward: I have a separate file src/styles/_variables.scss that contains my custom colors as scss-variables and also the $theme variable, that I am using later in src/theme.scss.

    @import '~@angular/material/theming';
    // Theme configuration
    $primary: mat-palette($mat-blue, 800, 500, 900);
    $accent:  mat-palette($mat-blue, A200, A100, A400);
    $warn: mat-palette($mat-red);
    
    $theme: mat-light-theme($primary, $accent, $warn);
    
    // Custom colors
    $custom-colors: (
      custom-color-a: mat-color($mat-green, 700),
      custom-color-b: mat-color($mat-red, 400),
    );
    $theme: map-merge($theme, (custom-colors: $custom-colors));
    

    To import my _variables.scss inside a component, I have to add stylePreprocessorOptions to the angular.json file:

    "styles": [
      "src/styles.scss",
      "src/theme.scss"
    ],
    "stylePreprocessorOptions": {
      "includePaths": [
        "src/styles"
      ]
    },
    

    Now I can import my variables in all scss-files of my components:

    @import 'variables';
    
    .custom-class-a {
      background-color: map-get($custom-colors, custom-color-a);
      color: map-get($custom-colors, custom-color-b);
    }
    

    Why do I use a sass-map and map-merge?

    As you noticed, I collect my custom colors in the sass-map $custom-colors and merge them into my $theme variable. This way I could either use my custom colors by directly importing it into my components style sheet (as described above) or I could use them inside my components @mixin the way it is described in the Angular Material documentation.

    @import '~@angular/material/theming';
    
    @mixin custom-component-theme($theme) {
      $custom-colors: map-get($theme, custom-colors);
    
      .custom-class-a {
        background-color: map-get($custom-colors, custom-color-a);
        color: map-get($custom-colors, custom-color-b);
      }
    }
    

    Maybe this combination is a way that your frontend devs could work with?

    0 讨论(0)
提交回复
热议问题