[Fixed] Create angular material theme with CSS variables

Issue

I’m working on a project that requires to be themeable at runtime. So I created a theme system that combines SCSS variable with CSS Variables.
This is how it looks.

:root {
  --primary-color: 196;
}


// Primary
$primary-100: hsl(var(--primary-color), 90%, 98%);
$primary-400: hsl(var(--primary-color), 90%, 65%);
$primary-main: hsl(var(--primary-color), 90%, 50%);
$primary-700: hsl(var(--primary-color), 90%, 30%);
$primary-900: hsl(var(--primary-color), 90%, 10%);

While this works amazingly with my custom components, I’m having a hard time making it work with the Material design theme system.

My thinking was that I will create the theme as explained in the Angular material docs, and instead of using static colors, I will use my SCSS variables. this is how my theme.scss file looks like.

@import '[email protected]/material/theming';
@import 'var.scss';

@include mat-core();

$shop-primary: (
  50: $primary-100,
  100: $primary-100,
  200: $primary-200,
  300: $primary-300,
  400: $primary-400,
 // ..... all other colors
  contrast: (
    50: $black-87-opacity,
    100: $black-87-opacity,
    200: $black-87-opacity,
     // ..... all other colors
  )
);


$shop-app-primary: mat-palette($shop-primary);
$shop-app-accent:  mat-palette($shop-primary);
$shop-app-warn: mat-palette($shop-primary);


$shop-app-theme: mat-light-theme($shop-app-primary, $shop-app-accent, $shop-app-warn);

@include angular-material-theme($shop-app-theme);

And I’m getting an error:

 Argument `$color` of `rgba($color, $alpha)` must be a color

Presumingly because the Angular Material mixin is expecting a color and not a hsl() value.

So my question is how would I be able to create a custom material theme with runtime CSS variables?

Solution

I created a little library to make this a little easier.

You can use it like so:

  1. Install:

    npm i angular-material-css-vars -S
    
  2. Then remove any existing @import '[email protected]/material/theming'; from your main stylesheet file.

  3. Add this to your main stylesheet instead:

    @import '~angular-material-css-vars/main';
    @include initMaterialCssVars();
    
  4. Change the main theme color like so:

    import {MaterialCssVarsService} from 'angular-material-css-vars';
    
    export class SomeComponentOrService {
      constructor(public materialCssVarsService: MaterialCssVarsService) {
        const hex = '#3f51b5';
        this.materialCssVarsService.changePrimaryColor(hex);
      }
    }
    

Leave a Reply

(*) Required, Your email will not be published