Ever spent hours trying to get that perfect icon to show up in your Angular app, only to end up with a frustrating square or a blurry mess?
I've been there too. Font icons seemed like the obvious choice until I realized they're actually holding us back. What if I told you there's a cleaner, more scalable way to handle icons in Angular Material that gives you pixel-perfect results every time?
Here's what you'll learn by the end of this article:
Why SVG icons are superior to font icons (and when you should make the switch)
How to properly configure Angular Material's mat-icon for SVG icons
Step-by-step setup with real code examples
Pro tips for organizing and optimizing your icon workflow
Common pitfalls and how to avoid them
Before we dive in—what's your biggest frustration with icons in Angular? Drop a comment below; I genuinely want to know what's been tripping you up!
Why SVG Icons Beat Font Icons Every Time
Let's be honest—font icons were a clever hack for their time, but they come with baggage:
Accessibility issues (screen readers struggle with them)
Loading dependencies (entire font files for a few icons)
Styling limitations (you're stuck with single colors)
Rendering inconsistencies across different browsers
SVG icons, on the other hand, are:
Scalable without quality loss
Accessible with proper ARIA labels
Lightweight (only load what you need)
Customizable (colors, gradients, animations)
Crisp on all screen densities
Setting Up Your Angular Material Project
First things first—let's make sure you have Angular Material properly installed. If you're starting fresh:
ng add @angular/material
Choose your theme, enable animations, and include the Angular Material typography styles when prompted.
Already have Angular Material? Perfect! Let's jump into the icon setup.
In your app.module.ts (or wherever you're importing Angular Material modules):
import { NgModule } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
// ... other imports
MatIconModule,
HttpClientModule, // Required for loading SVG icons
],
// ... rest of your module
})
export class AppModule { }
Why do we need HttpClientModule? Angular Material fetches SVG icons via HTTP requests, so this is essential for the setup to work.
Step 2: Register Your SVG Icons
Here's where the magic happens. In your component or service, you'll register your SVG icons with Angular Material's MatIconRegistry:
import { Component, OnInit } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer
) {}
ngOnInit() {
// Register a single SVG icon
this.matIconRegistry.addSvgIcon(
'custom-user',
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/user.svg')
);
// Register an entire icon set
this.matIconRegistry.addSvgIconSet(
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/icon-set.svg')
);
}
}
Hold up—what's with the DomSanitizer? Angular's security model blocks external resources by default. The bypassSecurityTrustResourceUrl method tells Angular that your SVG files are safe to load.
Step 3: Use Your SVG Icons in Templates
Now comes the satisfying part—actually using your icons:
<mat-icon svgIcon="custom-user"></mat-icon>
<mat-icon>home</mat-icon>
<mat-icon svgIcon="custom-user" class="large-icon"></mat-icon>
And in your CSS:
.large-icon {
width: 48px;
height: 48px;
font-size: 48px;
}
mat-icon {
color: #3f51b5;
}
mat-icon:hover {
color: #303f9f;
transform: scale(1.1);
transition: all 0.2s ease;
}
Quick question for you: Are you currently using font icons in your Angular project? What's holding you back from switching to SVG?
Pro Tip: Create an Icon Service
For larger projects, I recommend creating a dedicated service to manage your icons. This keeps your components clean and your icon registration centralized:
import { Injectable } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
@Injectable({
providedIn: 'root'
})
export class IconService {
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer
) {
this.registerIcons();
}
private registerIcons(): void {
const icons = [
'user',
'settings',
'dashboard',
'notifications',
'logout'
];
icons.forEach(icon => {
this.matIconRegistry.addSvgIcon(
icon,
this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/icons/${icon}.svg`)
);
});
}
}
Then inject this service in your AppComponent constructor:
export class AppComponent {
constructor(private iconService: IconService) {
// Icons are automatically registered when the service is injected
}
}
Step 4: Organize Your SVG Files
Here's how I structure my icon assets:
src/
assets/
icons/
ui/
user.svg
settings.svg
dashboard.svg
social/
facebook.svg
twitter.svg
linkedin.svg
actions/
save.svg
delete.svg
edit.svg
This organization makes it easy to:
Common Pitfalls (And How to Avoid Them)
1. Forgetting the HttpClientModule
// This won't work without HttpClientModule
this.matIconRegistry.addSvgIcon(...)
// Import HttpClientModule in your module
imports: [HttpClientModule, MatIconModule]
2. SVG viewBox Issues Make sure your SVG files have proper viewBox attributes:
<svg viewBox="0 0 24 24" xmlns="<http://www.w3.org/2000/svg>">
</svg>
3. Icon Not Showing Up Check your browser's network tab—you might see 404 errors for missing SVG files.
4. Security Errors Always use DomSanitizer.bypassSecurityTrustResourceUrl() when registering icons.
Bonus: Icon Sets for Multiple Namespaces
Want to organize icons by category? Use icon sets with namespaces:
// Register namespaced icon sets
this.matIconRegistry.addSvgIconSetInNamespace(
'ui',
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/ui-icons.svg')
);
this.matIconRegistry.addSvgIconSetInNamespace(
'social',
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/social-icons.svg')
);
Then use them like this:
<mat-icon svgIcon="ui:user"></mat-icon>
<mat-icon svgIcon="social:facebook"></mat-icon>
1. Lazy Load Icons Only register icons when they're needed:
async loadDashboardIcons() {
const icons = await import('./dashboard-icons');
icons.registerDashboardIcons(this.matIconRegistry, this.domSanitizer);
}
2. Use Angular's Built-in Icon Library For common icons, consider using Angular Material's built-in icons:
<mat-icon>home</mat-icon>
<mat-icon>settings</mat-icon>
<mat-icon>person</mat-icon>
3. Optimize Your SVG Files Use tools like SVGO to compress your SVG files:
npm install -g svgo
svgo assets/icons/*.svg
Let's put it all together with a practical example:
// navigation.component.ts
export class NavigationComponent implements OnInit {
menuItems = [
{ icon: 'dashboard', label: 'Dashboard', route: '/dashboard' },
{ icon: 'custom-user', label: 'Profile', route: '/profile' },
{ icon: 'settings', label: 'Settings', route: '/settings' },
{ icon: 'logout', label: 'Logout', route: '/logout' }
];
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer
) {}
ngOnInit() {
this.registerCustomIcons();
}
private registerCustomIcons() {
this.matIconRegistry.addSvgIcon(
'custom-user',
this.domSanitizer.bypassSecurityTrustResourceUrl('assets/icons/user.svg')
);
}
}
<nav class="sidebar">
<div class="nav-item" *ngFor="let item of menuItems">
<mat-icon
[svgIcon]="item.icon.startsWith('custom-') ? item.icon : null"
class="nav-icon">
{{ item.icon.startsWith('custom-') ? '' : item.icon }}
</mat-icon>
<span class="nav-label">{{ item.label }}</span>
</div>
</nav>
.sidebar {
.nav-item {
display: flex;
align-items: center;
padding: 12px 16px;
cursor: pointer;
transition: background-color 0.2s ease;
&:hover {
background-color: #f5f5f5;
}
.nav-icon {
margin-right: 12px;
color: #666;
}
.nav-label {
font-size: 14px;
color: #333;
}
}
}
Try this yourself: Can you modify the example above to add hover animations to the icons? Share your solution in the comments!
What's Next?
You now have everything you need to implement SVG icons in your Angular Material projects. But don't stop here—consider exploring:
Icon animation libraries like LottieFiles for complex animations
Icon generation tools that create optimized SVG sprites
Design system integration for consistent icon usage across teams
Key Takeaways
SVG icons are superior to font icons for modern web applications
Angular Material's mat-icon makes SVG integration straightforward
Proper organization and service-based architecture scales well
Performance optimization keeps your app fast and responsive
Security considerations are handled by Angular's DomSanitizer
Let's Keep the Conversation Going!
I want to hear from you:
What did you learn? Have you tried implementing SVG icons in your Angular project yet? What challenges did you face?
Drop a comment below—I read every single one and often turn great questions into future articles!
🔥 Found this helpful? 👏 Hit that clap button (or give it 5 claps!) so other developers can discover this guide too.
🚀 Follow Me for More Angular & Frontend Goodness:
I regularly share hands-on tutorials, clean code tips, scalable frontend architecture, and real-world problem-solving guides.
💼 LinkedIn — Let’s connect professionally
🎥 Threads — Short-form frontend insights
🐦 X (Twitter) — Developer banter + code snippets
👥 BlueSky — Stay up to date on frontend trends
🌟 GitHub Projects — Explore code in action
🌐 Website — Everything in one place
📚 Medium Blog — Long-form content and deep-dives
💬 Dev Blog — Free Long-form content and deep-dives
✉️ Substack — Weekly frontend stories & curated resources
🧩 Portfolio — Projects, talks, and recognitions
✍️ Hashnode — Developer blog posts & tech discussions
🎉 If you found this article valuable:
Let’s build cleaner, faster, and smarter web apps — together.
Stay tuned for more Angular tips, patterns, and performance tricks! 🧪🧠
✨ Share Your Thoughts To 📣 Set Your Notification Preference