Custom theming in Angular Material

Angular material comes with a few pre-built themes, such as the well-known indigo / pink color combination, which can be referenced simply by loading predefined .css files that are part of the Material library, e.g. indigo-pink.css.

Custom themes using predefined color palette:

These pre-built themes are very useful for testing or quick prototypes, but they will hardly ever match your desired webapp color scheme. For real-life use cases, its easily possibe to override themes using custom color combinations. Have a look at Material Design’s predefined color palette, and choose those colors that match your primary and accent color (and, optionally, warning color). To combine those into a custom themewe use the angular-material-theme mixin:

First, make sure common styles for Angular Material are included somewhere within your app – if not, include them:

@include mat-core();

Now we reference the chosen colors from the Material color palette and combine them into a theme:

$customtheme-primary: mat-palette($mat-light-green);
$customtheme-accent:  mat-palette($mat-deep-orange);
$customtheme-warn:    mat-palette($mat-red); // optional - we might skip this one

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

Alternatively, the according function mat-dark-theme is also available.

Finally, the angular-material-theme mixin applies our newly created theme:

@include angular-material-theme($customtheme);

Now, all Material controls should follow the new theme and be displayed in the desired primary and / or accent colors!

Get the best out of the Material color palette:

When scrolling through the Material color palette page, you’ll notice that multiple shades are defined for each color. Angular Material decides which one to display for what part of a user control, the default value is always the shade marked as 500 in the palette overview. However, to achieve a somewhat lighter or darker overall look-and-feel, we can specify the default color hue to be used. This includes specifying three indices in addition to the color palette, indicating the default, lighter, and darker hue to be used for this color.

This means, if we’d like to use a ligher orange color as accent throughout without using an other orange palette, we could adapt the code snippet from above to use the lightest shades of the deep-orange palette, namely the 50, 100, and 200 lines respectively:

$customtheme-primary: mat-palette($mat-light-green);
$customtheme-accent:  mat-palette($mat-deep-orange, 100, 50, 200);
$customtheme-warn:    mat-palette($mat-red);

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

@include angular-material-theme($customtheme);

Custom themes using custom color palette:

The above is nice as it gives us some flexibility in defining app theming, however at some point you might notive that the predefined colors don’t ecactly match your corporate design and, e.g., do not fit your company logo that is displayed in the web app. This is where custom color palettes come in:

In principle, it’s really easy to specify custom colors instead of referencing one of the predefined color palettes. However, remember that Material Design color palettes always specify 14 different hue values (50 – 900, A100 – A700), and expects these nuances to also be defined for custom palettes. To ensure equally distributed shades that match predefined color schemes, I strongly advice you to use some tool for automatically creating the hue table. For example, the Material Design Palette Generator expects a basic color value (this is your CD color to used as either primary, accent, or warn color), uses this as default (500) shade and automatically creates the other hue values.

After playing around with the palette generator, assign a unique name (ideally, this will include primary, accent, or warn) let it also generate the CSS code – for our example, choose Angular JS 2 (Material 2), and copy the code to your project. It will look somewhat similar to the following (except for the concrete color values, of course):

$md-accentcolor: (
    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 : #000000,
        100 : #000000,
        200 : #000000,
        300 : #ffffff,
        400 : #ffffff,
        500 : #ffffff,
        600 : #ffffff,
        700 : #ffffff,
        800 : #ffffff,
        900 : #ffffff,
        A100 : #000000,
        A200 : #ffffff,
        A400 : #ffffff,
        A700 : #ffffff,
    )
);

You’ll notice that, in addition to the 50 – 900 and A100 – A700 hue values, also contrast values have been created. These are always either white or black, and defines for each component that is filled with the according hue shade, which color the foreground will get. Do not change these values, as the automatically created ones ensure best accessibility and readability.

Repeat this code generation for each color you want to replace – it might not be necessary for all three primary, accent and warn since custom colors can be combined with predefined ones. In any case, we can reference the custom created color palette in exactly the same way as before:

$customtheme-primary: mat-palette($mat-light-green);
$customtheme-accent:  mat-palette($md-accentcolor, 100, 50, 200);
$customtheme-warn:    mat-palette($mat-red);

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

@include angular-material-theme($customtheme);