DEV Community

Nephi Wright
Nephi Wright

Posted on

Theming Material Design - Colors

Usually I find Googles documentation to be pretty good at describing the basics, however, when I started trying to edit the color scheme for a project built on Angular Material for the first time, the documentation provided many details on why - but not enough in the way of how. This information is useful, but all I really needed to know at this point is how to make a color scheme work on my site.

The Material Angular site had examples on theming here https://material.angular.io/guide/theming which provided what I thought was a good example of how to change the theme with scss:

@import '~@angular/material/theming';
// Plus imports for other components in your app.

// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);

// The warn palette is optional (defaults to red).
$candy-app-warn:    mat-palette($mat-red);

// Create the theme object (a Sass map containing all of the palettes).
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);

// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($candy-app-theme);
Enter fullscreen mode Exit fullscreen mode

The Problem

I expected $mat-indigo to be a single color from which the shades were generated. My expectations were wrong. The goal of the documentation appears to be to show you how to use one of the predefined themes. If you try providing a single color, like I did, you will get the error message:

ERROR in ./src/styles.scss (./node_modules/@angular-devkit/build-angular/src/angular-cli-files/plugins/raw-css-loader.js!./node_modules/postcss-loader/src??embedded!./node_modules/sass-loader/lib/loader.js??ref--15-3!./src/styles.scss)
Module build failed (from ./node_modules/sass-loader/lib/loader.js):

    default: map-get($base-palette, $default),
            ^
      $map: #4b0082 is not a map.
     ╷
1262 │     default: map-get($base-palette, $default),
     │              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     ╵
  node_modules/@angular/material/_theming.scss 1262:14  mat-palette()
  stdin 46:20                                           root stylesheet
      in /home/user/site/node_modules/@angular/material/_theming.scss (line 1262, column 14)
Enter fullscreen mode Exit fullscreen mode

This is a bit cryptic, but it did lead me to the solution. Drop the manual and read the source.

The Solution

This happens because the mat-palette mixin requires a color map not a single color. I figured out how to build my own palette by reading the _theming.scss source code and the default palette definitions in the _palette.scss source code but here is an example of the basic structure required for mat-palette:

$mat-indigo: (
  50: #e8eaf6,
  100: #c5cae9,
  200: #9fa8da,
  300: #7986cb,
  400: #5c6bc0,
  500: #3f51b5,
  600: #3949ab,
  700: #303f9f,
  800: #283593,
  900: #1a237e,
  A100: #8c9eff,
  A200: #536dfe,
  A400: #3d5afe,
  A700: #304ffe,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $light-primary-text,
    400: $light-primary-text,
    500: $light-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
    A100: $dark-primary-text,
    A200: $light-primary-text,
    A400: $light-primary-text,
    A700: $light-primary-text,
  )
);
Enter fullscreen mode Exit fullscreen mode

Note also that Angular Material provides many existing palettes for you to use and what follows here gives an example of using a built in palette named mat-blue-grey with another by creating the proper map. In the end the entire file for my theme looked like this:

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

// this defines a map for an orange color palette
$bc-accent-palette: (
   50: #FFF3E0,
  100: #FFE0B2,
  200: #FFCC80,
  300: #FFB74D,
  400: #FFA726,
  500: #FF9800,
  600: #FB8C00,
  700: #F57C00,
  800: #EF6C00,
  900: #E65100,
 A100: #FFD180,
 A200: #FFAB40,
 A400: #FF9100,
 A700: #FF6D00,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $dark-primary-text,
    400: $dark-primary-text,
    500: $light-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
    A100: $dark-primary-text,
    A200: $dark-primary-text,
    A400: $dark-primary-text,
    A700: $light-primary-text,
  )
);

// Build the theme palettes out of an existing palette and a custom one.
$bc-theme-primary: mat-palette($mat-blue-grey);
$bc-theme-accent:  mat-palette($bc-accent-palette, A200, A100, A400);

// Build the theme and include it in your styles.
$bc-theme: mat-light-theme($bc-theme-primary, $bc-theme-accent);
@include angular-material-theme($bc-theme);
Enter fullscreen mode Exit fullscreen mode

For this example, I simply used the color scheme defined for mat-orange - but I am just getting started on this project; I expect to tweak it quite a bit as I move forward. Defining the colors in this way gives you more control to customize the entire site's theme moving forward. However, if you just want to generate a css to use instead, you might try exploring the resources Angular provides. This allows you to export your color scheme to apps and also CodePen to view the specifics.

Top comments (0)