Create angular material theme with CSS variables

angular material css variables
angular css variables
change scss variables dynamically
angular material theme generator
sass dynamic theme
dynamic css variables
change css theme dynamically
angular bind css variable

I am 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 am 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 '~@angular/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 am 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?

If you upgrade to @angular/material 7.3.4 CSS Variables will mostly work. Only riples and other stuff that uses opacity will need a little fix. I use rgba() for my project, but it should also work for hsla()

Include this:

@function mat-color($palette, $hue: default, $opacity: null) {
    @if type-of($hue) == number and $hue >= 0 and $hue <= 1 {
        @return mat-color($palette, default, $hue);
    }

    $color: map-get($palette, $hue);

    @if (type-of($color) != color) {
        @if ($opacity == null){
            @return $color;
        }

        // Here is the change from the original function:
        // If the $color resolved to something different from a color, we assume it is a CSS variable
        // in the form of rgba(var(--rgba-css-var),a) and replace the 'a' value.
        @return #{str-slice($color, 0, str-index($color, ',')) + $opacity + ')'};
    }

    @return rgba($color, if($opacity == null, opacity($color), $opacity));
}

directly after:

@import '~@angular/material/theming';

and define your colors like this:

--primary-color-50-parts: 0,158,224;
// ... all other colors

$color-primary: (
    50: rgba(var(--primary-color-50-parts), 1),
    // ... all other colors
);

if you define your colors in the map like this:

50: hsla(var(--primary-color), 90%, 98%, 1);

then you need to change str-index($color, ',') in the sass function to something that finds the last ',' in the string. Unfortunatelly my sass knowledge covers only the bare minimum and I don't know how to do that :/

Build Truly Dynamic Theme with CSS Variables, You can use the MaterialCssVariables enum from here to make sure you get the variable name right. Rudimentary dark theme support via body class. Dynamically change theme of Angular Material Instead of using one single color for primary color, Angular Material asks for a color palette for primary color when we customize theme. Basically a

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 '~@angular/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);
      }
    }
    

johannesjo/angular-material-css-vars: Little library to use , In Angular Material, a theme is created by composing multiple palettes. Angular Material comes prepackaged with several pre-built theme css files. CSS Variables In Angular. Even if you don’t use Material design systems this is a pretty baseline. First lets map that theme to a TypeScript object that we can TYPE! YES, typed CSS!

What about material-theme-creator?

https://www.npmjs.com/package/material-theme-creator

npm i material-theme-creator

  @import '~@angular/material/theming';
  @import "~material-theme-creator/core";

  $primary-map: create-theme-map('primary');
  $accent-map: create-theme-map('accent');
  $warn-map: create-theme-map('warn');

  :root {
    @include create-variables-from-map('primary', $mat-teal);
    @include create-variables-from-map('accent', $mat-deep-purple);
    @include create-variables-from-map('warn', $mat-red);
  }

  // Light theme 
  @include angular-material-theme(mat-light-theme(mat-palette($primary-map), mat-palette($accent-map), mat-palette($warn-map)));
  // Dark theme 
  //@include angular-material-theme(mat-dark-theme(mat-palette($primary-map), mat-palette($accent-map), mat-palette($warn-map))); 

Theming Angular Material, Global variables in CSS will enable us to define theme variables that multiple components can use. To define a CSS custom property, we must� npm install -g @angular/cli. Then create our app. ng new project-crypto. And finally, generate a module to hold our theming logic. cd project-crypto ng generate module theme Code. Alright, time for the good stuff. Define CSS Variables. Let’s start by defining out initial CSS variables. We can set them initially to reflect our light theme.

Sooo... css variables are runtime, not compile time. SASS doesn't know what to do with them. You should be able to refactor your css vars using the ${} interpolation of SCSS and have everything still work the same. http://sass-lang.com/documentation/file.SASS_REFERENCE.html#interpolation_

$primary-color: 196;

:root {
  --primary-color: #{$primary-color};
}

$primary-100: hsl($primary-color, 90%, 98%);

Theming Angular apps with CSS Custom Properties, In this post, we will build a super simple cryptocurrency listing app using Angular 7 and CSS variables. Table of Contents. Design; Project� To create a custom theme in Angular material, you’ll have to import the theming service from the Angular Material and add the base style like given below. @import '~@angular/material/theming'; @include mat-core (); /* ===== Angular material custom themes ===== */ The mat-palette function takes some parameters to define a new theme.

How to create themes for your Angular 7 apps using CSS Variables, I am 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� Global variables in CSS will enable us to define theme variables that multiple components can use. To define a CSS custom property, we must prefix the property key with two dashes like the following --primary-color: #fff;. We can now reference the variable we defined in other CSS rules.

Create angular material theme with CSS variables - css - html, Angular Material provides theme support as part of its library. with Angular Material from the ground up to create custom themes that requires We opted to use css variables to do this and try to limit the variables to a small� Disclaimer: css vars are awesome but the way I use them in this post is not the best “angular-way” since I’m using elementRef.nativeElement instead of rendere2, currently (Feb 2019 ) it seems that renderer.setStyle() wont work with css vars.. this.renderer.setStyle(this.elementRef.nativeElement, key, theme[key]); **/

Theme support with Angular Material, Especially nowadays, where things like CSS variables and modules exist. These tools are great and they solve many different problems in a very� In our introduction to Angular Material 2, we showed how to use one of the pre-built themes, but it’s just as easy to create a custom theme.This will allow you to specify primary, accent and warning colors that will be used on Angular Material components.

Comments
  • I just tested my project using the hsl() scss function and it works correctly. Do you have the "stylePreprocessorOptions": { "includePaths": [ "src","src/assets/scss" ] } property in your angular.json so your var.scss can be picked up globally?
  • are you sure you are using mat-palette correctly ? i can't find an example where the pass an array to it
  • @Budhead2004 My var.scss is included perfectly fine. I use it all over the place.
  • @Budhead2004 did you pass in a CSS variable to the hsl function?
  • Can you show me what the contents of the $var you are passing into the hsl() function? @Dirk He is using the mat-palette function correctly, that's exactly how my custom theme is setup.
  • Wow! Sounds good, I did not have time to check it out, but this seems legit!
  • works pretty well together with @function colorToVariable($hexColor) { @return "#{red($hexColor)},#{green($hexColor)},#{blue($hexColor)}"; } and later --color-primary-lighter: #{colorToVariable(#ff0000)}; to avoid the manual rgb conversion
  • I don't need SCSS to know what to do with it, SCSS will just place it at the assigned value and the browser will interpret it. Second of all, the reason why I want this is that I should be able to change the theme at run time.