Customize Angular Material Design

Angular: The Full Gamut Edition

Charlie Greenman
August 27, 2020
12 min read

Razroo Best Practices

Razroo best practice is that the easiest way to get your app up and running is to use Material Design within your Angular application. Generally, an organization will want to roll its own theme into Angular Material. When that happens, the developer will have to go ahead and customize the build for material design. Let’s talk about how we can go ahead and do that, and how relatively simple it is.

Understanding Colors In Material

First and foremost, it is important to understand something called a color palette. I know some of you might be aware of what it is, but personally, I was not aware. A color palette in the digital world, refers to the full range of colors that can be displayed on a device. Within a Material Design application, it refers to the range of colors that can be used within the application. Material’s design language makes use of two main colors for it’s color palette. That would be primary and secondary values.

Primary and Secondary Values

  1. Primary — Color displayed most frequently across your app’s screens and components.
  2. Secondary — ”Provides more ways to accent and distinguish your product.” This includes:
  • Floating Action Button(Literally buttons that float over main content)
  • Selection controls(sliders, switches etc.)
  • Highlighting selected text
  • Progress bars
  • Links and headlines

Material Color Maps

Based on a primary value, Material will create a color map to used within different components across its library. It will then create a series of light and dark variants based on primary and secondary values. The primary and second values must be a map of colors going from lightest(50) to darkest(900).

The Material team has already created a series of 16 pre-defined color maps, for use with its design system. An example of material green color map, for instance, will look something like this:

$mat-green: (
  50: #e8f5e9,
  100: #c8e6c9,
  200: #a5d6a7,
  300: #81c784,
  400: #66bb6a,
  500: #4caf50,
  600: #43a047,
  700: #388e3c,
  800: #2e7d32,
  900: #1b5e20,
  A100: #b9f6ca,
  A200: #69f0ae,
  A400: #00e676,
  A700: #00c853,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $dark-primary-text,
    400: $dark-primary-text,
    500: $dark-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: $dark-primary-text,

For primary values, the most used value will start to be 500. For secondary values, the most used value will is 200. The significance of these values is that Material Design will follow a Hierarchical system. The darker the color is, the more of an emphasis we are placing on that button. The lighter it is, the less emphasis we are placing on that element.

You might be wondering about two things. For starters, why is it that the values progress by 100’s? Second, what is up with the values that have an ”A” attached to the left side? Values progress by 100’s is merely a convention used by Material Design. Other design frameworks progress by 10’s(IBM Design) instead of 100’s, for instance, or even by 1’s(Open Color). It is merely a convention used to show that values are progressing. Values attached with an A on the left side, are Accent colors. Accent colors are colors used for emphasis within a color scheme. In particular, within the setting of Angular, these are used within”

  1. Text fields and cursors
  2. Text Selection
  3. Progress Bars
  4. Selection controls, buttons, and sliders links

The contrast color map is used by Angular to display the appropriate text color based on the respective non-contrast color map.

Material Design and Sass

In Angular, Sass tends to be the de-facto CSS pre-processor that is used across multiple libraries in Angular. Material Design unexpectedly offers Sass functionality out of the box, and makes it incredibly easy to customize your environment based on sass overrides. Let’s install Angular Material, so that we can use Material’s Sass Library, and customize the theme as we see appropriate.

Npm Install Material Theme

First and foremost, let’s make sure that we have properly installed and Angular Material in our Angular application.

npm install --save @angular/material @angular/cdk @angular/animations

You package.json will now include packages needed to use Angular Material within the application in general. In addition, the package (@angular/material) to make the Sass changes we so dearly need.

Import Material Design and Call Core Styles

The next step, is for us to go ahead and import Material Design in our styles.scss file. The styles.scss file can be found in the root Angular application src folder.

@import '~@angular/material/theming’; // always include only once per project 
@include mat-core();

You will notice that we are adding a tilda(~)next to the node module folder, containing the sass file we need. This tells sass that the file we would like to import is located inside of the node_modules folder.

What the above does is import the theming.scss file that contains all of the theming variables for material design. We are also calling the mat-core() function, which is a:

Mixin that renders all of the core styles that are not theme-dependent.

Using The Material Light + Dark Theme

Angular offers out of the box in the _theming.scss file a light and dark theme function. The function looks as follows:

@function mat-light-theme($primary, $accent, $warn: mat-palette($mat-red)) {
  @return (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    is-dark: false,
    foreground: $mat-light-theme-foreground,
    background: $mat-light-theme-background,

It takes in two required parameters:

1. Primary — Primary color
2. Accent — Accent color

In addition, one optional parameter called `warn`, which by default will be red. So, let’s say we wanted to create a custom theme based on some of the values that Angular provides. We can use the functionality the Angular Material team provides out of the box. In particular, the mat-light theme.

$px-app-primary: mat-palette($mat-green); $px-app-accent: mat-palette($mat-yellow);
$px-theme: mat-light-theme($px-app-primary, $px-app-accent); @include angular-material-theme($px-theme);

Now all of our Angular Material components will be using our unique theme. (Granted this is based on pre-built colors Angular has provided, but you get the point.)

Creating Our Own Custom Theme

Quite common is that your organization will want to layer their own custom theme outside of the 16 colors that Angular provides. This might manifest its self in two scenarios:

  1. A new primary and secondary color
  2. A new background, and foreground color as well.

Designers have a tool that allows them to automatically generate the appropriate color in their design by supplying a singular color. Angular developers have that luxury as well. There are tools that will do that for you. My personal favorite is the Material Design Palette Generator. You will then have the ability to click on the clipboard icon, click on the dropdown for Angular JS 2 (Material 2), and copy the scss variable map. It’s really as simple as that.


Create a _themes.scss file

Being that we are creating our own themes, the cleanest thing for us to do would be to place it in it’s own themes.scss file. In addition, assuming that the organization is going to build out more applications, giving it the ability to plug and play the companies theme, will really speed up development for other parts of the company. That being said, Razroo best practices is to create a lib folder for styles.

|-- common/
|-- |-- styles/
|-- |-- |-- _themes.scss

and inside of our styles folder, we are going to create a _themes.scss file. Our generated themes using our primary, or secondary colors might look something like this:

$razroo-primary-blue: (
  50 : #e7f2f4,
  100 : #c3dee4,
  200 : #9cc8d3,
  300 : #74b2c1,
  400 : #56a2b3,
  500 : #3891a6,
  600 : #32899e,
  700 : #2b7e95,
  800 : #24748b,
  900 : #17627b,
  A100 : #b3eaff,
  A200 : #80dcff,
  A400 : #4dcfff,
  A700 : #33c8ff,
  contrast: (
    50 : #000000,
    100 : #000000,
    200 : #000000,
    300 : #000000,
    400 : #000000,
    500 : #ffffff,
    600 : #ffffff,
    700 : #ffffff,
    800 : #ffffff,
    900 : #ffffff,
    A100 : #000000,
    A200 : #000000,
    A400 : #000000,
    A700 : #000000,

It’s quite a bit of code, but I just wanted to visualize that all of this is created by using the Material Design Palette Generator. I.e. what you can expect when you do the same.

Using Libs themes.scss file

Inside of our styles.scss file, we can import our \_themes.scss file. Assuming we are just changing the primary color and secondary color, we can do the following:

@import '~@angular/material/theming'; 
@import 'libs/common/styles/_themes';
//@include angular-material-theme($mat-light-theme-background);
$razroo-theme: mat-light-theme(mat-palette($razroo-primary-blue), mat-palette($razroo-secondary-red));
@include angular-material-theme($razroo-theme);

We now have custom themes that we have created. With the architecture we setup, they are available globally to be used by other applications/teams. In addition, using the Angular mat-light-theme function(mat-dark-theme also an option), or app is now using our exclusive theme.

Background + Foreground

It is important to mention that per the Material Design guidelines, background, and foreground are not meant to represent a brand. They are more so used to convey the energy of the application. For that reason, the Material Team does not offer a way of the box to change it. For Razroo’s Pixel Illustrator(the world’s most complete open-source enterprise application that Razroo will be open-sourcing soon), we wanted to create a very vibrant application. This meant that we wanted to use our own background and foreground colors. Doing something like this requires a bit more effort probably from the Material team expecting you to do it less. There are four steps required to change the background to what you want.

  1. Generate color theme maps, using the Material Design Palette Generator
  2. Create a background theme, and foreground theme for our application.
  3. Create our own custom theme function.
  4. Creating a default background for HTML + body being that this will only work as an override for material design components.
// Background palette for light themes.
$razroo-theme-background: (
  status-bar: map_get($razroo-background-yellow, 300),
  map_get($razroo-background-yellow , map_get($razroo-background-yellow),
  map_get($razroo-background-yellow , rgba(map_get($razroo-background-yellow, 500), 0.04), 
  // TODO(kara): check style with Material Design UX
  card: map_get($razroo-background-yellow , 500),
  dialog: map_get($razroo-background-yellow , 500),
  disabled-button: rgba(map_get($razroo-background-yellow, 500), 0.12), raised-button: map_get($razroo-background-yellow , 500),
  focused-button: $dark-focused,
  selected-button: map_get($razroo-background-yellow , 300),
  selected-disabled-button: map_get($razroo-background-yellow , 400), disabled-button-toggle: map_get($razroo-background-yellow , 200), unselected-chip: map_get($razroo-background-yellow , 300), disabled-list-option: map_get($razroo-background-yellow, 200),

Your team should have a designer who figures out what the opposite color of your background is, in order to create a foreground color. However, you can use a tool such as Color Tool’s Opposite Color Tool. Granted that you do not have a designer as a resource.

Use the background + foreground color by designer, and follow up with the Material Design Color Palette tool, and create the appropriate color map.

@function razroo-theme($primary, $accent, $warn: mat-palette($mat-red)) {
  @return (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    is-dark: false,
    foreground: $mat-light-theme-foreground,
    background: $razroo-theme-background,
$razroo-theme: razroo-theme(mat-palette($razroo-primary-blue), mat-palette($razroo-secondary-red));

// Inject $razroo-theme across angular-material-theme
@include angular-material-theme($razroo-theme);  

html, body {
  width: 100%;
  height: 100%;
  background-color: map_get($razroo-background-yellow, 50);

Angular Material will not change the HTML and body background. You will have to go ahead, and do that yourself.

Overriding Components

After we have overridden our theme in general across the app, there will be times wherein we will need to override specific styles for the component. There really isn’t any way to modify the styling ahead of time. The only way is to target the specific material component’s class and to modify it when appropriate at run time. However, what we can do, is consolidate all of our overridden components in a singular place, so that it is well organized. For instance, let’s say that we have a dialog that we would like to remove the default padding for in some scenarios, but keep it in others. We would put a dialog file inside of our material overrides folder. Our folder/file structure will look like the following:

 |-- common/
 |-- |--styles/
 |-- |-- |--material-overrides/
 |-- |-- |-- |--_dialog.scss
 |-- |-- |-- |-- _material-overrides.scss
 |-- |-- |-- |--_themes.scss

We import every material override into the main _material-override.scss file. Then, import the material-override file in our main styles.scss file.

Overriding Overlay Components

Overlay components are unique from an Angular Material perspective. You will actually have the ability to target a specific class. If you wish to override an overlay component, overlay components have a panelClass property that can be used to target the overlay pane. For instance, with regards to dialogs, we have the ability to add a class doing the following:, {panelClass: 'razroo-no-padding-dialog'});

Now, we have the option to apply a CSS theme specifically to the razroo-no-padding-dialog class.

.myapp-no-padding-dialog .mat-dialog-container {
  padding: 0;

This gives us freedom moving forward so that we can have multiple appearances for our material components.

Overriding Non Overlay Components

Non-overlay components, do not have the option to add a panelClass to be target using CSS. The only solution which truly makes sense, and is sustainable, is to create a global override on the component itself. So, let’s say that we wanted to change the appearance of our material card components. Perhaps make the padding a little less pronounced. We would do the following:

.mat-card {
  // this will be 8px
  padding: rz-space-multiplier(1);

Wrapping Up

Material is, and will for a very long time, be the premier design language for Angular. It is incredibly simple to set up, and a breeze to modify. I am incredibly thankful to the Angular team for all they have done to integrate Material out of the box. In my humble opinion, it is one of the three greatest architectural decisions a team can make for Angular(State management, and extensive unit testing being the others). In my humble opinion, I believe it can knock off 2 months of development time, from a team of 3 over the course of 2 years.

More articles similar to this


Razroo is committed towards contributing to open source. Take the pledge towards open source by tweeting, #itaketherazroopledge to @_Razroo on twitter. One of our associates will get back to you and set you up with an open source project to work on.