08 July 2020
tags: css scss material

I had an interesting scenario today where I had to apply a local modified theme, in addition to a global theme. By scss setup looks like:

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

@include  mat-core();

@mixin custom-cmp($theme) {

  $foreground: map-get($theme, foreground);

  $primary: map-get($theme, primary);
  $accent: map-get($theme, accent);
  $warn: map-get($theme, warn);

  [my-custom-comp],
  .my-custom-comp
  {
    &[text],
    &.text
    {
      color: mat-color($foreground, text);
    }
    &[primary],
    &.primary
    {
      color: mat-color($primary);
    }

    &[accent],
    &.accent
    {
      color: mat-color($accent);
    }

    &[warn],
    &.warn
    {
      color: mat-color($warn);
    }
  }
}

$my-theme-primary: mat-palette($mat-indigo);
$my-theme-accent: mat-palette($mat-amber);
$my-theme-warn: mat-palette($mat-red);

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

@include angular-material-theme($my-theme);
@include custom-cmp($my-theme);

$my-dark-theme-primary: mat-palette($mat-blue);
$my-dark-theme-accent:  mat-palette($mat-amber, A200, A100, A400);
$my-dark-theme-warn:    mat-palette($mat-red);
$my-dark-theme:   mat-dark-theme($my-dark-theme-primary, $my-dark-theme-accent, $my-dark-theme-warn);

[darktheme=true]
{
  @include angular-material-theme($my-dark-theme);
  @include custom-cmp($iv-dark-theme);
}

[darktheme=false]
{
  @include angular-material-theme($iv-theme);
  @include custom-cmp($iv-theme);
}

... and the top level darktheme attribute is used to control the global theming.

Use !important #

I did not want to use !important unless absolutely necessary (also, I couldn't get the syntax to work in the 10 minutes I was trying it).

Use class #

My next attempt was to add higher level css priority to the local component. This SO post seems to suggest that the css priority goes by:

ID > class > attribute

My attempt was to add:


[darktheme=true],
.darktheme // <-- added
{
  @include angular-material-theme($my-dark-theme);
  @include custom-cmp($iv-dark-theme);
}

[darktheme=false],
.lighttheme // <-- added
{
  @include angular-material-theme($iv-theme);
  @include custom-cmp($iv-theme);
}

It did not seem to work. Later parsed CSS attributes were taking precedent, suggesting class and attribute have the same priority (at least in Chrome Version 83.0.4103.116 (Official Build) (64-bit))

Further increase CSS priority #

Then, I remembered a trick to artificially boost the priority


[darktheme=true],
.darktheme.darktheme
{
  @include angular-material-theme($my-dark-theme);
  @include custom-cmp($iv-dark-theme);
}

[darktheme=false],
.lighttheme.lighttheme
{
  @include angular-material-theme($iv-theme);
  @include custom-cmp($iv-theme);
}

Note to self: should investigate CSS priority.