How to Create Custom Theme in Angular Material 16

Last Updated on by in Angular Material
In this Angular Material custom theme example tutorial, we will explore how to create custom theme in Angular Material from scratch in less than 5 minutes.Angular material offers pre-built ui themes with primary, warning, and accent color options.

If you are working on a real-world angular application, in that case, you might need to create a custom angular material theme to make your project brand look better.

Let’s understand what theme is according to Angular material. An Angular material theme is the set of colors that will be applied to the Angular Material components.

Angular material theme is built on the material design pattern.

Get Started with Angular Project Setup

I assume you already have set up Node JS, NPM & Angular CLI in your system. Let’s get started and set up the Angular project.

ng new angular-material-theme

# ? Would you like to add Angular routing? Yes
# ? Which stylesheet format would you like to use? SCSS

Go inside project folder.

cd angular-material-theme

Remove Angular TypeScript Errors

To get rid from the errors, set below properties to false in tsconfig.json file:

"compilerOptions": {
 ...
 ...
   "strict": false,
   "noPropertyAccessFromIndexSignature": false,
 ...
 ...
},
  "angularCompilerOptions": {
    "strictTemplates": false
  }

Implementing Angular Material UI Library

Run the given below command to install Material library:

ng add @angular/material

Select any theme among Angular Material Pre-built Themes:

? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink

❯ Indigo/Pink        [ Preview: https://material.angular.io?theme=indigo-pink ] 
  Deep Purple/Amber  [ Preview: https://material.angular.io?theme=deeppurple-amber ] 
  Pink/Blue Grey     [ Preview: https://material.angular.io?theme=pink-bluegrey ] 
  Purple/Green       [ Preview: https://material.angular.io?theme=purple-green ]

Select Yes for including Angular Material Typography and Animations packages.

# ? Set up global Angular Material typography styles? Yes
# ? Set up browser animations for Angular Material? Yes

Complete Angular material documentation can be found here.

Head over to src/styles.scss file, add the below styling code:

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: "Roboto", sans-serif;
}

.header {
  justify-content: space-between;
}

.mat-sidenav-container {
  height: 100%;
  display: flex;
  flex: 1 1 auto;
}

.mat-nav-list .mat-list-item {
  font-size: 15px;
}

.nav-tool-items {
  display: inline-block;
  margin-right: 13px;
}

.mat-sidenav,
.mat-sidenav-content {
  padding: 15px;
}

.mat-list-item.active {
  background: rgba(0, 0, 0, 0.04);
}

.mat-sidenav-content {
  padding: 25px 40px 0;
}

.mat-sidenav {
  background-color: #f2f2f2;
  width: 250px;
}

.header {
  position: sticky;
  position: -webkit-sticky;
  top: 0;
  z-index: 1000;
}

mat-sidenav mat-icon {
  margin-right: 12px;
}

.hamburger {
  margin-top: 5px;
  cursor: pointer;
}

.mat-radio-button,
.mat-radio-group {
  margin-right: 25px;
}

.controlers-wrapper > * {
  width: 100%;
  padding: 0;
}

.misc-bottom-padding {
  margin: 8px 0 10px;
}

.misc-bottom-padding mat-label {
  margin-right: 15px;
}

mat-radio-group mat-radio-button {
  margin-left: 5px;
}

.button-wrapper button {
  margin-right: 5px;
}

table.mat-table,
table {
  width: 100%;
}

body .mat-list-item {
  margin-bottom: 10px;
}

.inner-wrapper {
  padding: 15px 0 130px;
  width: 100%;
}

.inner-wrapper mat-card {
  display: inline-block;
  margin: 0 6% 0 0;
  vertical-align: top;
  width: 44%;
}

.full-wrapper {
  width: 100%;
}

.multiple-items {
  position: relative;
}

.multiple-items .tooltip-info {
  right: 0;
  top: 7px;
  cursor: pointer;
  color: #a1a7c7;
  position: absolute;
  font-size: 20px;
}

body .push-right {
  margin-right: 10px;
}

.no-data {
  text-align: center;
  padding-top: 30px;
  color: #6c75a9;
}

.button-wrapper {
  margin: 20px 0 0 0;
}

.example-card {
  max-width: 400px;
}

.example-header-image {
  background-image: url("https://material.angular.io/assets/img/examples/shiba1.jpg");
  background-size: cover;
}

.title-group {
  margin-bottom: 25px;
}

.card-deck-container {
  width: 100%;
  max-width: 1200px;
  position: relative;
  border-radius: 2px;
  padding: 10px 10px 30px;
  margin: 10px 10px 10px 10px;
  background-color: #f5f5f5;
}

.card-item {
  padding: 3px 3px 3px 3px;
}

mat-grid-tile {
  background: lightblue;
}

.my-alternate-theme button {
  margin-right: 10px;
}

@media (max-width: 1024px) {
  .inner-wrapper mat-card {
    width: 100%;
  }

  .mat-sidenav-content {
    padding: 20px 20px 0;
  }

  .misc-bottom-padding mat-label {
    display: block;
    padding-bottom: 10px;
  }

  .mat-sidenav {
    width: 230px;
  }

  .mat-nav-list .mat-list-item {
    font-size: 14px;
  }
}

@media (max-width: 767px) {
  .nav-tool-items {
    margin-right: 0;
  }

  .hamburger {
    visibility: visible !important;
  }
}

In the later part of this guide, we will also learn to create custom angular material theme.

Hence, we will src/theme.scss file and add the below code into the file.

@use '@angular/material' as mat;

@include mat.core();

Next, we need to register and import material styling files in angular.json file under styles array:

"styles": [
      "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
      "src/styles.scss",
      "src/theme.scss"
],

Create Angular Material Module File

Let’s create a separate Angular material module file. to manage Angular material UI components.

Go to angular-material.module.ts file and include the following code.

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { OverlayModule } from '@angular/cdk/overlay';
import { CdkTreeModule } from '@angular/cdk/tree';
import { PortalModule } from '@angular/cdk/portal';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatRippleModule } from '@angular/material/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTreeModule } from '@angular/material/tree';
import { MatBadgeModule } from '@angular/material/badge';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatRadioModule } from '@angular/material/radio';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatTooltipModule } from '@angular/material/tooltip';


const materialModules = [
  CdkTreeModule,
  MatAutocompleteModule,
  MatButtonModule,
  MatCardModule,
  MatCheckboxModule,
  MatChipsModule,
  MatDividerModule,
  MatExpansionModule,
  MatIconModule,
  MatInputModule,
  MatListModule,
  MatMenuModule,
  MatProgressSpinnerModule,
  MatPaginatorModule,
  MatRippleModule,
  MatSelectModule,
  MatSidenavModule,
  MatSnackBarModule,
  MatSortModule,
  MatTableModule,
  MatTabsModule,
  MatToolbarModule,
  MatFormFieldModule,
  MatButtonToggleModule,
  MatTreeModule,
  OverlayModule,
  PortalModule,
  MatBadgeModule,
  MatGridListModule,
  MatRadioModule,
  MatDatepickerModule,
  MatTooltipModule
];

@NgModule({
  imports: [
    CommonModule,
    ...materialModules
  ],
  exports: [
    ...materialModules
  ],
})

export class AngularMaterialModule { }

Import Angular Material module file inside the app.module.ts file.

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AngularMaterialModule } from './angular-material.module';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AngularMaterialModule,
    FormsModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})

export class AppModule {}

We are done with all setup now we’re ready to go!

Create Angular Material Basic Layout

In order to create a basic template, we should go to Angular Material official site and check out the UI components there.

Go to app.component.html file and paste the following code.

<!-- Toolbar -->
<mat-toolbar color="primary" class="header">
  <div>Material Theme</div>
  <span class="nav-tool-items">
    <mat-icon (click)="sidenav.toggle()" class="hamburger">menu</mat-icon>
  </span>
</mat-toolbar>

<mat-sidenav-container>
  <!-- Sidenav -->
  <mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'over' : 'side'" [(opened)]="opened" [fixedInViewport]="true"
    [fixedTopGap]>
    <mat-nav-list>
      <a mat-list-item>
        <mat-icon>dashboard</mat-icon> Dashboard
      </a>
      <a mat-list-item>
        <mat-icon>person</mat-icon> User Profile
      </a>
      <a mat-list-item>
        <mat-icon>content_paste</mat-icon> Table List
      </a>
      <a mat-list-item>
        <mat-icon>library_books</mat-icon> Typography
      </a>
      <a mat-list-item>
        <mat-icon>location_on</mat-icon> Maps
      </a>
      <a mat-list-item>
        <mat-icon>calendar_today</mat-icon> Calendar
      </a>
    </mat-nav-list>
  </mat-sidenav>

  <!-- Main content -->
  <mat-sidenav-content>

    <!-- Applying the mat-tyography class adds styles for native elements. -->
    <section class="mat-typography title-group">
      <h1>Heading Goes Here</h1>
      <mat-divider></mat-divider>
    </section>

    <!-- Angular material cards -->
    <div class="productCards">
      <mat-grid-list cols="4" rowHeight="200px">
        <mat-grid-tile [colspan]="3" [rowspan]="1">1
        </mat-grid-tile>
        <mat-grid-tile [colspan]="1" [rowspan]="2">2
        </mat-grid-tile>
        <mat-grid-tile [colspan]="1" [rowspan]="1">3
        </mat-grid-tile>
        <mat-grid-tile [colspan]="2" [rowspan]="1">4
        </mat-grid-tile>
      </mat-grid-list>
    </div>

  </mat-sidenav-content>
</mat-sidenav-container>

Go to app.component.ts file and paste the following code.

import { Component, ViewChild, HostListener } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent {
  opened = true;
  @ViewChild('sidenav', { static: true }) sidenav: MatSidenav;

  ngOnInit() {
    console.log(window.innerWidth)
    if (window.innerWidth < 768) {
      this.sidenav.fixedTopGap = 55;
      this.opened = false;
    } else {
      this.sidenav.fixedTopGap = 55;
      this.opened = true;
    }
  }

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    if (event.target.innerWidth < 768) {
      this.sidenav.fixedTopGap = 55;
      this.opened = false;
    } else {
      this.sidenav.fixedTopGap = 55
      this.opened = true;
    }
  }

  isBiggerScreen() {
    const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    if (width < 768) {
      return true;
    } else {
      return false;
    }
  }

}

Creating Angular Material Custom Theme

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.

@use '@angular/material' as mat;

@include mat.core();
@use '@angular/material' as mat;

@include mat.core();


$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);

// The "warn" palette is optional and defaults to red if not specified.
$my-warn: mat.define-palette(mat.$red-palette);

To style primary, accent, and warning color themes you must declare the color variables name using the mat-palette function.

Create Angular Material Dark Theme

At the moment, we are using mat-light-theme() mixin function. Now here comes the easy part, we can create a dark angular material theme by just using the mat-dark-theme() mixin.

Creating a dark Angular Material theme is pretty easy and straight-forward task. You just have to follow the given below process.

// Convert => mat-light-theme()
$my-custom-theme: mat-light-theme($my-custom-primary, $my-custom-accent);

// Convert to this => mat-dark-theme()
$my-custom-theme: mat-dark-theme($my-custom-primary, $my-custom-accent);

Check out the demo:

Create Angular Material Dark Theme

Create Alternative Themes in Angular Material

Creating an alternate theme in angular material is not that difficult. All you have to do just declared the alternate theme in your theme.scss file.

Now, go to terminal and run the below command to run your project.

ng serve --open

Angular Material Theme

If you need any help related to this tutorial then you can found the GitHub.

Don’t forget to share this tutorial if you found this useful, thanks for checking this tutorial out.

Have a good day.