DEV Community

Cover image for How to Use SVG Icons with Angular Material's mat-icon Component (The Right Way)
Rajat
Rajat

Posted on

How to Use SVG Icons with Angular Material's mat-icon Component (The Right Way)

Stop fighting with icon fonts—here's how to set up scalable, crisp SVG icons in Angular Material that actually work


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

Enter fullscreen mode Exit fullscreen mode

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.


Step 1: Configure the MatIconModule

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 { }

Enter fullscreen mode Exit fullscreen mode

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')
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

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:

<!-- Using a registered custom icon -->
<mat-icon svgIcon="custom-user"></mat-icon>

<!-- Using Material Design icons (if you have the icon font loaded) -->
<mat-icon>home</mat-icon>

<!-- Styling your icons -->
<mat-icon svgIcon="custom-user" class="large-icon"></mat-icon>

Enter fullscreen mode Exit fullscreen mode

And in your CSS:

.large-icon {
  width: 48px;
  height: 48px;
  font-size: 48px;
}

// Custom colors
mat-icon {
  color: #3f51b5;
}

// Hover effects
mat-icon:hover {
  color: #303f9f;
  transform: scale(1.1);
  transition: all 0.2s ease;
}

Enter fullscreen mode Exit fullscreen mode

👇 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`)
      );
    });
  }
}

Enter fullscreen mode Exit fullscreen mode

Then inject this service in your AppComponent constructor:

export class AppComponent {
  constructor(private iconService: IconService) {
    // Icons are automatically registered when the service is injected
  }
}

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

This organization makes it easy to:

  • Find icons quickly
  • Maintain consistent naming
  • Scale your icon library
  • Implement icon namespacing if needed

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]

Enter fullscreen mode Exit fullscreen mode

2. SVG viewBox Issues
Make sure your SVG files have proper viewBox attributes:

<!-- ✅ Good SVG structure -->
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <!-- icon content -->
</svg>

Enter fullscreen mode Exit fullscreen mode

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')
);

Enter fullscreen mode Exit fullscreen mode

Then use them like this:

<mat-icon svgIcon="ui:user"></mat-icon>
<mat-icon svgIcon="social:facebook"></mat-icon>

Enter fullscreen mode Exit fullscreen mode

Performance Optimization Tips

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);
}

Enter fullscreen mode Exit fullscreen mode

2. Use Angular's Built-in Icon Library
For common icons, consider using Angular Material's built-in icons:

<!-- No registration needed -->
<mat-icon>home</mat-icon>
<mat-icon>settings</mat-icon>
<mat-icon>person</mat-icon>

Enter fullscreen mode Exit fullscreen mode

3. Optimize Your SVG Files
Use tools like SVGO to compress your SVG files:

npm install -g svgo
svgo assets/icons/*.svg

Enter fullscreen mode Exit fullscreen mode

Real-World Example: Building a Navigation Menu

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')
    );
  }
}

Enter fullscreen mode Exit fullscreen mode
<!-- navigation.component.html -->
<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>

Enter fullscreen mode Exit fullscreen mode
/* navigation.component.scss */
.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;
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

💡 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.


🎯 Your Turn, Devs!

👀 Did this article spark new ideas or help solve a real problem?

💬 I'd love to hear about it!

✅ Are you already using this technique in your Angular or frontend project?

🧠 Got questions, doubts, or your own twist on the approach?

Drop them in the comments below — let’s learn together!


🙌 Let’s Grow Together!

If this article added value to your dev journey:

🔁 Share it with your team, tech friends, or community — you never know who might need it right now.

📌 Save it for later and revisit as a quick reference.


🚀 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:

  • Leave a 👏 Clap
  • Drop a 💬 Comment
  • Hit 🔔 Follow for more weekly frontend insights

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

Top comments (0)