Angular Material is a powerful UI component library that brings Google’s Material Design to Angular applications. Whether you're building a dashboard, form-heavy app, or a responsive layout, Angular Material provides ready-to-use, well-tested components that help you create professional and consistent user interfaces with minimal effort. In this tutorial, you’ll learn how to use some of the most commonly used Angular Material components—like buttons, cards, forms, dialogs, and tables—through practical examples. By the end, you'll have a solid foundation for building modern Angular applications with Material Design components.
1. Create a New Angular Project
Make sure you have the Angular CLI installed globally:
npm install -g @angular/cli
Then create a new Angular project:
ng new angular-material-components
During setup, you'll be asked:
- Would you like to add Angular routing? → You can say Yes or No, depending on whether you’ll need navigation.
- Which stylesheet format would you like to use? → Select CSS (or SCSS, if you prefer).
After setup, navigate to the project folder:
cd angular-material-components
Serve the App
Run the development server:
ng serve
Then open your browser to http://localhost:4200 to see your new Angular app running.
2. Install Angular Material
Run this command inside your project folder:
ng add @angular/material
This will trigger a setup wizard. You'll be asked:
1. Choose a prebuilt theme
→ Select one (e.g., Indigo/Pink or Deep Purple/Amber are popular)
2. Set up global typography styles?
→ Type Yes
3. Set up animations?
→ Type Yes
The CLI will:
- Add Angular Material, Angular CDK, and Animations packages
- Update your angular.json with the selected theme
- Import BrowserAnimationsModule into your AppModule
You’re now ready to start using Material components!
3. Add a Material Button (MatButtonModule)
Import MatButtonModule in src/app/app.component.ts:
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@Component({
selector: 'app-root',
imports: [MatButtonModule],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'angular-material-components';
}
To ensure animations are enabled, run this command inside your project folder:
npm install @angular/animations
Check your app.config.ts:
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimations()]
};
Update your app.component.html like this:
<h1>Angular Material Buttons</h1>
<button mat-button>Flat Button</button>
<button mat-raised-button color="primary">Raised Button</button>
<button mat-stroked-button color="accent">Stroked Button</button>
4. Add a Material Card (MatCardModule)
Import MatCardModule by updating your app.component.ts like this:
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'app-root',
imports: [MatButtonModule, MatCardModule],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'angular-material-components';
}
Update your app.component.html like this:
<div style="padding: 16px;">
<mat-card>
<mat-card-header>
<mat-card-title>Angular Material Card</mat-card-title>
<mat-card-subtitle>With header and content</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>This is an example of a Material card component.</p>
<button mat-raised-button color="accent">Click Me</button>
</mat-card-content>
</mat-card>
</div>
5. Add a Material Toolbar (MatToolbarModule)
Import MatToolbarModule by updating your import list:
import { MatToolbarModule } from '@angular/material/toolbar';
Then add it to the imports array:
imports: [MatButtonModule, MatCardModule, MatToolbarModule],
Update your app.component.html like this:
<mat-toolbar color="primary">Djamware Angular Material App</mat-toolbar>
<div style="padding: 16px;">
<mat-card>
<mat-card-header>
<mat-card-title>Angular Material Card</mat-card-title>
<mat-card-subtitle>With header and content</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>This is an example of a Material card component.</p>
<button mat-raised-button color="accent">Click Me</button>
</mat-card-content>
</mat-card>
</div>
6. Add Form Field and Input (MatFormFieldModule + MatInputModule)
You need ReactiveFormsModule (or FormsModule) for working with form controls.
Run this if not already installed:
npm install @angular/forms
Then import ReactiveFormsModule from @angular/forms. Update app.component.ts with an Input Field:
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { ReactiveFormsModule, FormControl } from '@angular/forms';
@Component({
selector: 'app-root',
imports: [
MatButtonModule,
MatCardModule,
MatToolbarModule,
MatFormFieldModule,
MatInputModule,
ReactiveFormsModule,
],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
nameControl = new FormControl('');
}
Update your app.component.html like this:
<mat-toolbar color="primary">Djamware Angular Material App</mat-toolbar>
<div style="padding: 16px;">
<mat-card>
<mat-card-header>
<mat-card-title>Angular Material Card</mat-card-title>
<mat-card-subtitle>With header and content</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>This is an example of a Material card component.</p>
<mat-form-field appearance="outline" style="width: 100%; margin-top: 16px;">
<mat-label>Enter your name</mat-label>
<input matInput [formControl]="nameControl" />
</mat-form-field>
<p>Your name: {{ nameControl.value }}</p>
<button mat-raised-button color="accent" style="margin-top: 8px;">
Submit
</button>
</mat-card-content>
</mat-card>
</div>
✅ Result
You now have:
- A styled Material input field
- Live binding showing the user’s input
- A submit button below it
7. Add a Material Dialog (Popup)
We'll:
- Create a simple dialog component.
- Open it from a button in the main component.
- Use MatDialog to control it.
Create a Dialog Component by creating a new file called src/app/example-dialog.component.ts. Add this code inside:
import { Component } from '@angular/core';
import { MatDialogModule } from '@angular/material/dialog';
import { MatButtonModule } from '@angular/material/button';
@Component({
standalone: true,
selector: 'app-example-dialog',
imports: [MatDialogModule, MatButtonModule],
templateUrl: './example-dialog.component.html',
})
export class ExampleDialogComponent { }
Create a new file called src/app/example-dialog.component.html. Add this code inside:
<h2 mat-dialog-title>Dialog Title</h2>
<div mat-dialog-content>
<p>This is a simple Angular Material dialog.</p>
</div>
<div mat-dialog-actions>
<button mat-button mat-dialog-close>Close</button>
</div>
Update your app.component.ts to:
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { ReactiveFormsModule, FormControl } from '@angular/forms';
import { ExampleDialogComponent } from './example-dialog.component';
import { MatDialogModule, MatDialog } from '@angular/material/dialog';
@Component({
selector: 'app-root',
imports: [
MatButtonModule,
MatCardModule,
MatToolbarModule,
MatFormFieldModule,
MatInputModule,
ReactiveFormsModule,
MatDialogModule
],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
nameControl = new FormControl('');
constructor(private readonly dialog: MatDialog) { }
openDialog() {
this.dialog.open(ExampleDialogComponent);
}
}
Update your app.component.html like this:
<mat-toolbar color="primary">Djamware Angular Material App</mat-toolbar>
<div style="padding: 16px;">
<mat-card>
<mat-card-header>
<mat-card-title>Angular Material Card</mat-card-title>
<mat-card-subtitle>With header and content</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<mat-form-field appearance="outline" style="width: 100%; margin-top: 16px;">
<mat-label>Enter your name</mat-label>
<input matInput [formControl]="nameControl" />
</mat-form-field>
<p>Your name: {{ nameControl.value }}</p>
<button mat-raised-button color="accent" style="margin-top: 8px;">
Submit
</button>
<button mat-raised-button color="primary" (click)="openDialog()" style="margin-left: 8px;">
Open Dialog
</button>
</mat-card-content>
</mat-card>
</div>
Run the app:
ng serve
Click the “Open Dialog” button — a modal popup should appear with a title, content, and a Close button.
8. Add a Material Table (MatTableModule)
We’ll build a simple table with static data and columns for name, email, and role. Update your app.component.ts to import MatTableModule:
import { MatTableModule } from '@angular/material/table';
Add it to the imports array:
imports: [
// other modules...
MatTableModule,
]
Below your existing buttons or card content in app.component.html, add this block:
<mat-card style="margin-top: 24px;">
<mat-card-title>User List</mat-card-title>
<table mat-table [dataSource]="users" class="mat-elevation-z8" style="width: 100%; margin-top: 16px;">
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Name</th>
<td mat-cell *matCellDef="let user">{{ user.name }}</td>
</ng-container>
<!-- Email Column -->
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef>Email</th>
<td mat-cell *matCellDef="let user">{{ user.email }}</td>
</ng-container>
<!-- Role Column -->
<ng-container matColumnDef="role">
<th mat-header-cell *matHeaderCellDef>Role</th>
<td mat-cell *matCellDef="let user">{{ user.role }}</td>
</ng-container>
<!-- Header and Row Declarations -->
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</mat-card>
Update your app.component.ts with:
displayedColumns: string[] = ['name', 'email', 'role'];
users = [
{ name: 'Alice Johnson', email: '[email protected]', role: 'Admin' },
{ name: 'Bob Smith', email: '[email protected]', role: 'User' },
{ name: 'Carol White', email: '[email protected]', role: 'Moderator' },
];
9. Add a Snackbar (Toast Notification)
We’ll add a snackbar that shows a success message when the user clicks the “Submit” button. Import MatSnackBarModule in app.component.ts:
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
Then include it in the imports array:
imports: [
// other modules...
MatSnackBarModule,
]
Update your Submit button in app.component.html to call a method:
<button mat-raised-button color="accent" style="margin-top: 8px;" (click)="submitName()">
Submit
</button>
Now, add the submitName() method in your component class:
constructor(private readonly dialog: MatDialog, private readonly snackBar: MatSnackBar) { }
submitName() {
const name = this.nameControl.value;
if (name) {
this.snackBar.open(`Hello, ${name}! Your name was submitted.`, 'Close', {
duration: 3000, // auto-hide after 3 seconds
horizontalPosition: 'right',
verticalPosition: 'top',
});
} else {
this.snackBar.open('Please enter your name first.', 'Close', {
duration: 3000,
horizontalPosition: 'right',
verticalPosition: 'top',
});
}
}
Snackbar Behavior
- Appears at the top-right
- Disappears automatically after 3 seconds
- The user can click “Close”
10. Add Angular Material Tabs (MatTabsModule)
We'll show:
- A tab group with 3 tabs
- Each tab with different content
Update your app.component.ts to import MatTabsModule:
import { MatTabsModule } from '@angular/material/tabs';
Add it to the imports array:
imports: [
// other modules...
MatTabsModule,
]
Add this block below your <mat-card> sections:
<mat-card style="margin-top: 24px;">
<mat-card-title>Angular Material Tabs</mat-card-title>
<mat-tab-group>
<mat-tab label="Overview">
<p style="padding: 16px;">
This is the overview tab. You can place any content here.
</p>
</mat-tab>
<mat-tab label="Users">
<p style="padding: 16px;">
You have {{ users.length }} users listed in the table above.
</p>
</mat-tab>
<mat-tab label="Settings">
<p style="padding: 16px;">
Settings tab content can include forms, toggles, or anything else.
</p>
</mat-tab>
</mat-tab-group>
</mat-card>
What You’ll See
- A card titled “Angular Material Tabs”
- Three switchable tabs: Overview, Users, Settings
- Each shows different content
- Fully responsive and styled
11. Add Angular Material Stepper (MatStepperModule)
We'll:
- Create a horizontal stepper
- Add two simple steps
- Use Angular FormBuilder to control the step state
Update your app.component.ts:
import { MatStepperModule } from '@angular/material/stepper';
import { ReactiveFormsModule, FormControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
Then add MatStepperModule to the imports array:
imports: [
// other modules...
MatStepperModule,
]
In your component class:
formGroup1!: FormGroup;
formGroup2!: FormGroup;
constructor(
private readonly dialog: MatDialog,
private readonly snackBar: MatSnackBar,
private readonly fb: FormBuilder
) { }
ngOnInit() {
this.formGroup1 = this.fb.group({
firstCtrl: ['', Validators.required],
});
this.formGroup2 = this.fb.group({
secondCtrl: ['', Validators.required],
});
}
Below your previous sections, add this:
<mat-card style="margin-top: 24px;">
<mat-card-title>Angular Material Stepper</mat-card-title>
<mat-horizontal-stepper [linear]="true" #stepper>
<mat-step [stepControl]="formGroup1">
<form [formGroup]="formGroup1">
<ng-template matStepLabel>Step 1: Basic Info</ng-template>
<mat-form-field appearance="outline" style="width: 100%;">
<mat-label>Enter something</mat-label>
<input matInput formControlName="firstCtrl" required />
</mat-form-field>
<div>
<button mat-button matStepperNext [disabled]="!formGroup1.valid">Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="formGroup2">
<form [formGroup]="formGroup2">
<ng-template matStepLabel>Step 2: Confirmation</ng-template>
<mat-form-field appearance="outline" style="width: 100%;">
<mat-label>Confirm input</mat-label>
<input matInput formControlName="secondCtrl" required />
</mat-form-field>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</form>
</mat-step>
</mat-horizontal-stepper>
</mat-card>
Result
- Step 1: Input something
- Step 2: Confirm it
- Linear navigation with validation
- The reset button clears the steps
12. Add Angular Material Sidenav (MatSidenavModule)
We’ll create:
- A basic layout with a toggleable side menu
- A toolbar on top
- Content area on the right
In your app.component.ts, import MatSidenavModule and Layout Modules:
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
Add them to your imports array:
imports: [
// other modules...
MatSidenavModule,
MatIconModule,
MatListModule,
]
Replace the top of your template (or add above the existing content) with the following:
<mat-sidenav-container class="example-container" style="height: 400px;">
<mat-sidenav #sidenav mode="side" opened>
<mat-nav-list>
<a mat-list-item href="#">Home</a>
<a mat-list-item href="#">Users</a>
<a mat-list-item href="#">Settings</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button mat-icon-button (click)="sidenav.toggle()" aria-label="Toggle sidenav">
<mat-icon>menu</mat-icon>
</button>
<span>My Angular Material App</span>
</mat-toolbar>
<div style="padding: 16px;">
<!-- Keep your existing components here -->
<p>This is the main content area.</p>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
In styles.scss (or app.component.scss if preferred), add:
.example-container {
border: 1px solid #ddd;
margin-top: 24px;
}
Result
- Sidebar on the left with nav links
- Toolbar with a menu button to toggle
- Content area to the right
- Fully responsive
13. Add Angular Material Datepicker (MatDatepickerModule)
We’ll:
- Add a date input using mat-datepicker
- Include a calendar pop-up
- Handle date selection in your form
Update your app.component.ts:
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatNativeDateModule } from '@angular/material/core';
Add these to the imports array:
imports: [
// other modules...
MatDatepickerModule,
MatNativeDateModule,
]
Add this block anywhere in your layout (e.g., inside a card or section):
<mat-card style="margin-top: 24px;">
<mat-card-title>Angular Material Datepicker</mat-card-title>
<mat-form-field appearance="outline" style="width: 100%; margin-top: 16px;">
<mat-label>Select a date</mat-label>
<input matInput [matDatepicker]="picker" [(ngModel)]="selectedDate">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<p *ngIf="selectedDate" style="margin-top: 12px;">
You picked: <strong>{{ selectedDate | date:'longDate' }}</strong>
</p>
</mat-card>
In your app.component.ts:
selectedDate!: Date;
Also, make sure FormsModule is in your imports (for [(ngModel)]):
import { FormsModule, ReactiveFormsModule, FormControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CommonModule } from '@angular/common';
imports: [
CommonModule,
// other modules...
FormsModule,
]
Result
- An input with a calendar pop-up
- The selected date is shown below
- Clean and native-style date selection
14. Add Angular Material Autocomplete (MatAutocompleteModule)
We’ll build:
- A searchable input with autocomplete options
- A list that filters based on user input
Update your app.component.ts:
import { MatAutocompleteModule } from '@angular/material/autocomplete';
And include it in your imports array:
imports: [
// other modules...
MatAutocompleteModule,
]
Add this section to your template:
<mat-card style="margin-top: 24px;">
<mat-card-title>Angular Material Autocomplete</mat-card-title>
<mat-form-field appearance="outline" style="width: 100%; margin-top: 16px;">
<mat-label>Choose a programming language</mat-label>
<input
type="text"
matInput
[formControl]="languageControl"
[matAutocomplete]="auto"
/>
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredLanguages" [value]="option">
{{ option }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</mat-card>
In app.component.ts, add:
import { FormControl } from '@angular/forms';
import { startWith, map } from 'rxjs/operators';
import { Observable } from 'rxjs';
languageControl = new FormControl('');
languages: string[] = ['JavaScript', 'TypeScript', 'Python', 'Go', 'Rust', 'Kotlin'];
filteredLanguages!: string[];
ngOnInit() {
this.filteredLanguages = this.languages;
this.languageControl.valueChanges
.pipe(
startWith(''),
map(value => this._filter(value || ''))
)
.subscribe(filtered => {
this.filteredLanguages = filtered;
});
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.languages.filter(lang =>
lang.toLowerCase().includes(filterValue)
);
}
Make sure ReactiveFormsModule is in your imports:
import { ReactiveFormsModule } from '@angular/forms';
imports: [
// other modules...
ReactiveFormsModule,
]
Result
- A smart input with real-time filtering
- Type “py” and see "Python"
- Easy UX for search + select
15. Add Angular Material Expansion Panel (MatExpansionModule)
We’ll:
- Add a basic accordion with multiple panels
- Use the expansion state to show/hide details
In your app.component.ts:
import { MatExpansionModule } from '@angular/material/expansion';
And include it in your imports array:
imports: [
// other modules...
MatExpansionModule,
]
Insert this into your template:
<mat-card style="margin-top: 24px;">
<mat-card-title>Angular Material Expansion Panel</mat-card-title>
<mat-accordion multi>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
What is Angular Material?
</mat-panel-title>
</mat-expansion-panel-header>
<p>Angular Material is a UI component library for Angular developers.</p>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
How do I install it?
</mat-panel-title>
</mat-expansion-panel-header>
<p>Run <code>ng add angular/material</code> to install and configure.</p>
</mat-expansion-panel>
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
Can I customize the theme?
</mat-panel-title>
</mat-expansion-panel-header>
<p>Yes! Angular Material supports custom themes and dark mode.</p>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
Result
- Clean, collapsible sections
- Multiple panels can be open (due to multiple)
- You can control which panel is expanded by default
16. Angular Material Chips and Badges
We’ll create:
- Removable chips with an input
- A badge (notification count) on an icon
In your app.component.ts:
import { MatChipsModule } from '@angular/material/chips';
import { MatBadgeModule } from '@angular/material/badge';
And include them in your imports array:
imports: [
// other modules...
MatChipsModule,
MatBadgeModule,
]
Add this to your component template:
<mat-card style="margin-top: 24px;">
<mat-card-title>Angular Material Chips</mat-card-title>
<mat-chip-set>
<mat-chip *ngFor="let tag of tags" [removable]="true" (removed)="removeTag(tag)">
{{ tag }}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-set>
<mat-form-field style="margin-top: 16px;" appearance="outline">
<mat-label>New Tag</mat-label>
<input matInput [(ngModel)]="newTag" (keydown.enter)="addTag()" placeholder="Press Enter to add" />
</mat-form-field>
</mat-card>
Add logic component, in app.component.ts:
tags: string[] = ['Angular', 'Material', 'UI'];
newTag: string = '';
notifications = 3;
messages = 7;
addTag() {
const tag = this.newTag.trim();
if (tag && !this.tags.includes(tag)) {
this.tags.push(tag);
}
this.newTag = '';
}
removeTag(tag: string) {
this.tags = this.tags.filter(t => t !== tag);
}
Result
- Chips: Add with Enter, remove with X
- Badges: Notification dots on icons
17. Angular Material Progress Spinner & Progress Bar
We’ll build:
- A spinner that shows during loading
- A progress bar (determinate & indeterminate)
In your app.component.ts, import the required modules:
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressBarModule } from '@angular/material/progress-bar';
And include them in the imports array:
imports: [
// other modules...
MatProgressSpinnerModule,
MatProgressBarModule,
]
In your HTML template, add template code:
<mat-card style="margin-top: 24px;">
<mat-card-title>Progress Spinner</mat-card-title>
<div style="text-align: center; margin: 16px 0;">
<mat-spinner *ngIf="isLoading" [diameter]="50"></mat-spinner>
<button mat-raised-button color="primary" (click)="toggleLoading()">
{{ isLoading ? 'Stop Loading' : 'Start Loading' }}
</button>
</div>
</mat-card>
<mat-card style="margin-top: 24px;">
<mat-card-title>Progress Bar</mat-card-title>
<div style="margin: 16px 0;">
<mat-progress-bar
*ngIf="showProgressBar"
mode="determinate"
[value]="progressValue"
></mat-progress-bar>
<button mat-raised-button color="accent" (click)="startProgress()">
Start Progress
</button>
</div>
</mat-card>
In app.component.ts, add component logic:
isLoading = false;
showProgressBar = false;
progressValue = 0;
progressInterval: any;
toggleLoading() {
this.isLoading = !this.isLoading;
}
startProgress() {
this.showProgressBar = true;
this.progressValue = 0;
clearInterval(this.progressInterval);
this.progressInterval = setInterval(() => {
if (this.progressValue >= 100) {
clearInterval(this.progressInterval);
setTimeout(() => (this.showProgressBar = false), 1000);
} else {
this.progressValue += 10;
}
}, 300);
}
Result
- 🔄 Spinner shows while isLoading is true
- 📊 Progress bar fills from 0 to 100%
- Buttons to trigger each
18. Angular Material Dark Theme & Custom Themes
Create a file named custom-theme.scss in the src folder:
@use '@angular/material' as mat;
@include mat.core();
// Light theme palettes
$light-primary: mat.m2-define-palette(mat.$m2-indigo-palette);
$light-accent: mat.m2-define-palette(mat.$m2-pink-palette);
$light-warn: mat.m2-define-palette(mat.$m2-red-palette);
// Dark theme palettes
$dark-primary: mat.m2-define-palette(mat.$m2-deep-purple-palette);
$dark-accent: mat.m2-define-palette(mat.$m2-lime-palette);
$dark-warn: mat.m2-define-palette(mat.$m2-orange-palette);
// Light theme definition
$light-theme: mat.m2-define-light-theme((color: (primary: $light-primary,
accent: $light-accent,
warn: $light-warn,
)));
// Dark theme definition
$dark-theme: mat.m2-define-dark-theme((color: (primary: $dark-primary,
accent: $dark-accent,
warn: $dark-warn,
)));
// Create classes to toggle
.light-theme {
@include mat.all-component-colors($light-theme);
}
.dark-theme {
@include mat.all-component-colors($dark-theme);
}
Reference the SCSS in angular.json, under styles, include custom-theme.scss:
"styles": [
"src/custom-theme.scss",
"src/styles.scss"
]
(Or combine into styles.scss if preferred.)
Add Theme Toggle Logic, in app.component.ts:
isDarkTheme = false;
toggleTheme() {
this.isDarkTheme = !this.isDarkTheme;
const themeClass = this.isDarkTheme ? 'dark-theme' : 'light-theme';
document.body.classList.remove('dark-theme', 'light-theme');
document.body.classList.add(themeClass);
}
Add toggle button in the template, in app.component.html:
<mat-card style="margin-top: 24px;">
<mat-card-title>Theme Toggle</mat-card-title>
<button mat-raised-button (click)="toggleTheme()">
Toggle {{ isDarkTheme ? 'Light' : 'Dark' }} Theme
</button>
</mat-card>
Result
- A toggle button that switches between dark and light themes
- Custom primary/accent colors are defined in your SCSS
- Applied across all Angular Material components!
Conclusion
In this tutorial, you’ve learned how to build a comprehensive Angular application using Angular Material components with standalone components and custom theming. From buttons, dialogs, snackbars, and navigation lists to form controls, data tables, progress indicators, and theme toggling, we’ve covered many of the most commonly used Material features. By implementing both light and dark themes with custom palettes, your app is now ready for a modern, responsive, and accessible UI experience. As Angular and Material continue to evolve, this foundation gives you the flexibility to scale and style your apps with ease.
You can find the full source code on our GitHub.
If you don’t want to waste your time designing your front-end or your budget to spend by hiring a web designer, then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.
That's just the basics. If you need more deep learning about MEAN Stack, Angular, and Node.js, you can take the following cheap course:
- Master en JavaScript: Aprender JS, jQuery, Angular 8, NodeJS
- Angular 8 - Complete Essential Guide
- Learn Angular 8 by creating a simple Full Stack Web App
- Angular 5 Bootcamp FastTrack
- Angular 6 - Soft & Sweet
- Angular 6 with TypeScript
Thanks!