Custom Theme for Angular Material Components Series: Part 1 — Create a Theme
Dharmen Shah
Posted on March 24, 2020
Updated version of this article is present at: angular-material.dev
Learn how to Create and Apply Custom Theme to different Angular Material Components. 😎
Context
In this series, I will write about creating and applying Custom Theme to different Angular Material Components.
Few days back, I was going through question on stack-overflow. A question regarding applying same theme to mat-sidenav
as mat-toolbar
appeared to my feed. You can check the question in below link:
I am hoping to have the background of a mat-sidenav
the same as my mat-toolbar
- theme color.
In src\styles.scss
I have:
@import '~@angular/material/prebuilt-themes/indigo-pink.css';
My template / HTML file has:
<mat-toolbar color="primary">
<button mat-icon-button (click)="sidenav.toggle()">
<mat-icon>menu</mat-icon>
</button>
Title text
</mat-toolbar>
That shows nicely as indigo menu bar with the menu
…
Although, I answered the question with sample code, I thought of expanding the same context to more components and make a nice formatted code-base. Which can be useful to my upcoming projects and yours, too.
By end of this series, you would have a nice idea about creating and applying your own Custom Theme for Angular Material Components.
Summary
I have made the series of three articles. Below is the summary of what we will be doing:
Part 1
- Create an Angular Project using Angular CLI and add Angular Material
- Understand Angular Material Custom Theme
- Create Base Theme Files
- Update Project Structure with few new modules
- Create basic UI skeleton
Part 2
Understand how Angular Material Theme works by a deep look into Angular Material’s repo.
Part 3
- Understand theme of MatToolbar
- Apply
MatToolbar
’s theme toMatSidenav
andMatDialog
(we won’t be applying theme to whole dialog, just to it’s header) - Apply a different theme to
MatSnackbar
and create nice styling for different kind of notifications (default, info, success, warning, error)
Let's begin...
1. Create an Angular Project using Angular CLI and add Angular Material
ng new theming-material-components --style=scss --skipTests=true --routing=true
Above command will create a project-folder named theming-material-components, with scss as our styling partner, routing and skipped testing. Once it’s done, just move to project directory and run below commands:
cd theming-material-components
ng serve -o
The output will be something like below:
Now, to add Angular Material, we will follow official guideline from : Angular Material Getting Started:
ng add @angular/material
When asked, use responses like below:
That will add all necessary packages, update index.html, main.ts, app.module.ts and style.scss files.
2. Understand Angular Material Custom Theme
Let’s look at style.scss file:
// Custom Theming for Angular Material
// For more information: https://material.angular.io/guide/theming
@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/
$theming-material-components-primary: mat-palette($mat-indigo);
$theming-material-components-accent: mat-palette($mat-pink, A200, A100, A400);
// The warn palette is optional (defaults to red).
$theming-material-components-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$theming-material-components-theme: mat-light-theme($theming-material-components-primary, $theming-material-components-accent, $theming-material-components-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($theming-material-components-theme);
/* You can add global styles to this file, and also import other style files */
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
Notice that Angular CLI has created a basic default theme for us. Comments in file are pretty much straight-forward, which will give you idea about how custom theming works. Below is the summary:
- Create primary
$theming-material-components-primary
, accent$theming-material-components-accent
and warn$theming-material-components-warn
colors from Material Color System. - Using above colors, create a lighter version of theme
$theming-material-components-theme
with the help ofmat-light-theme
. - Finally, include your custom theme in Angular Material’s Theme builder called
angular-material-theme
, which is responsible for making all your components’ themes in-align with your custom theme.
3. Create Base Theme Files
// theme.scss
// 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/
$theming-material-components-primary: mat-palette($mat-indigo);
$theming-material-components-accent: mat-palette($mat-pink, A200, A100, A400);
// The warn palette is optional (defaults to red).
$theming-material-components-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$theming-material-components-theme: mat-light-theme($theming-material-components-primary, $theming-material-components-accent, $theming-material-components-warn);
You can change the colors as per your requirements, but I will keep them as defaults.
I will also create one more file named custom-component-themes.scss like below:
// custom-component-themes.scss
// import custom componenet themes
// you only have to add additional componenets here (instead of in every theme class)
@mixin custom-components-theme($theme) {}
Basically, this file will contain all of our components’ themes. We will talk about the same later on.
Let’s import both : theme.scss and custom-component-themes.scss in our main styles.scss and include their mixins, so our updated file will look like below:
// styles.scss
// Custom Theming for Angular Material
// For more information: https://material.angular.io/guide/theming
@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();
// import our custom theme
@import './theme.scss';
// import custom componenet themes
@import './custom-component-themes.scss';
// 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($theming-material-components-theme);
@include custom-components-theme($theming-material-components-theme);
/* You can add global styles to this file, and also import other style files */
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
To understand more about use of Material Colors in Creation of Custom Material Theme, you can read a nice article by Tomas Trajan:
4. Update Project Structure with few new modules
As of now, our project structure is something like below:
Let’s create a module, which will have all of our Angular Material modules.
ng g m custom-material
That will create a file and folder : custom-material/custom-material.module.ts . Let’s add couple of modules from Angular Material modules in it:
// app/custome-material/custom-material.module.ts
import { NgModule } from "@angular/core";
import { MatSidenavModule } from "@angular/material/sidenav";
import { MatSliderModule } from "@angular/material/slider";
import { MatSlideToggleModule } from "@angular/material/slide-toggle";
import { MatToolbarModule } from "@angular/material/toolbar";
@NgModule({
exports: [
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatToolbarModule
]
})
export class CustomMaterialModule {}
Now, let’s create a shared module, which will be a home to all of our shared modules, components, directives, pipes and services.
ng g m shared
Now, let’s add our CustomMaterialModule
in imports
array of SharedModule
:
// app/shared/shared.module.ts
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { CustomMaterialModule } from "../custom-material/custom-material.module";
@NgModule({
declarations: [],
imports: [CommonModule, CustomMaterialModule]
})
export class SharedModule {}
And let’s import SharedModule
in AppModule
:
// app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SharedModule } from './shared/shared.module'; // 🆕 <-- Added
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
SharedModule // 🆕 <-- Added
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
5. Create basic UI skeleton
Let’s create a shared component SideNavComponent
which we will use in our AppComponent
:
ng g c shared/components/sidenav
Let’s update the content of sidenav.component.html , sidenav,component.scss and sidenav.component.ts :
// app/shared/components/sidenav/sidenav.component.html
<mat-toolbar [color]="themeColor">
Toolbar
</mat-toolbar>
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav mode="side" opened> Sidenav content</mat-sidenav>
<mat-sidenav-content>
<ng-content></ng-content>
</mat-sidenav-content>
</mat-sidenav-container>
// app/shared/components/sidenav/sidenav.component.scss
.example-container {
height: 500px;
}
// app/shared/components/sidenav/sidenav.component.ts
import { Component, OnInit, Input } from "@angular/core";
@Component({
selector: "app-sidenav",
templateUrl: "./sidenav.component.html",
styleUrls: ["./sidenav.component.scss"]
})
export class SidenavComponent implements OnInit {
@Input() themeColor = "";
constructor() {}
ngOnInit() {}
}
Notice the @Input() themeColor
property of component. We will be using this property to assign same theme to sidenav and toolbar (and other component in next part).
Let’s add SidenavComponent
to exports
array of SharedModule
:
// app/shared/shared.module.ts
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { CustomMaterialModule } from "../custom-material/custom-material.module";
import { SidenavComponent } from "./components/sidenav/sidenav.component";
@NgModule({
declarations: [SidenavComponent],
imports: [CommonModule, CustomMaterialModule],
exports: [SidenavComponent] // 🆕 <-- Added
})
export class SharedModule {}
👉 Pro Tip: Don’t forget to export all the components/pipes/directives which we are going to make in
SharedModule
.
Now, let’s remove everything from app.component.html and replace it like below:
// app/app.component.html
<app-sidenav [themeColor]="'primary'">
Main Content
</app-sidenav>
If you change the [themeColor] to warn or accent , it will change effectively:
Now, the project structure is something like below:
Phew..!! You are done with basic project setup. You deserve 3 claps… 👏 👏 👏
If you are thinking that we haven’t done much yet, I wouldn’t say you’re wrong. But, basic setup, custom theme introduction and understanding is needed before we move ahead.
Thank You,
for reading this article. This was my first article on medium. Let me know your feedback in comments section.
In the next part we will learn how Angular Material’s Theme works. We will also take a deep look into Angular Material’s report and understand the relation between stylesheets.
Wait..!! Where’s the code man !!??
Whatever we’ve created in this article, I have combined them as an Angular Project, and uploaded on GitHub:
Next part is also published:
Custom Theme for Angular Material Components Series: Part 2 — Understand Theme
Dharmen Shah for ITNEXT ・ Apr 3 '20
That’s it, see you next time. And yes, always believe in yourself.
Credits
Cover image credit Photo by Moose
Begin image credit: Photo by Danielle MacInnes on Unsplash
Footer image credit: link
Posted on March 24, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
April 3, 2020