Beyond the Defaults: A Guide to Customizing Angular Material Themes

Leader posted 4 min read

Angular Material is an incredible toolkit for building polished UIs quickly. You can get a great-looking app by just picking one of the pre-built themes. But what happens when your project's brand guidelines call for a specific shade of blue that isn't in the default palette?

That's where the real power of Angular Material shines: its SASS-based theming API. This guide will show you how to move beyond the defaults, create your own custom themes, and master the modern Sass module system (@use and @forward) along the way.


## The Core of Material Theming

Before we write any code, let's understand the basic building blocks. An Angular Material theme is simply a Sass map containing configuration for:

  1. Color: A theme is defined by three color palettes:
    • primary: The main color used across your app (e.g., for headers, primary buttons).
    • accent: A secondary color used to highlight key UI elements (e.g., floating action buttons, links, form controls).
    • warn (or error): A color for indicating error states or dangerous actions.
  2. Typography: Configuration for font families, sizes, and weights.
  3. Density: Settings to control the spacing and size of components (e.g., for more compact UIs).

For this guide, we'll focus on color, as it's the most common customization.


## Example: Creating a Custom Theme

Let's say we want to create a theme with a Teal primary color and an Amber accent color.

### Step 1: Set Up Your Theme File

First, create a new file in your src folder called custom-theme.scss. This is where all our theming logic will live.

### Step 2: Use @use Instead of @import

The Sass team has deprecated @import in favor of a modern module system using @use. This is the recommended approach for all new Angular projects.

Why @use is better:

  • No Global Mess: It loads styles into a local namespace, preventing conflicts where variables or mixins from different files overwrite each other.
  • Loads Once: No matter how many times you @use a file, its code is executed only once.
  • Explicit: You know exactly where every mixin and function is coming from.

At the top of your custom-theme.scss, add the following line. This imports the Material theming functions and assigns them to the mat namespace.

// src/custom-theme.scss
@use '@angular/material' as mat;

### Step 3: Define Custom Palettes

Next, we'll define our color palettes. Angular Material provides helper functions and pre-defined color palettes for this. A palette is a map of color hues from 50 to 900 with lighter and darker variants.

We'll use mat.define-palette to create our primary, accent, and warn palettes.

// src/custom-theme.scss
@use '@angular/material' as mat;

// Include the core styles that are required for all components.
@include mat.core();

// 1. Define your color palettes
$my-primary: mat.define-palette(mat.$teal-palette, 700, 500, 900);
$my-accent: mat.define-palette(mat.$amber-palette, A200, A100, A400);
$my-warn: mat.define-palette(mat.$red-palette);

Here, mat.define-palette takes the base palette (e.g., mat.$teal-palette) and three optional arguments: the default hue, a lighter hue, and a darker hue.

### Step 4: Create and Apply the Theme

Now we combine our palettes into a single theme object using mat.define-light-theme (or mat.define-dark-theme).

// 2. Create the theme object
$my-theme: mat.define-light-theme((
  color: (
    primary: $my-primary,
    accent: $my-accent,
    warn: $my-warn,
  )
));

// 3. Apply the theme to all Angular Material components
@include mat.all-component-themes($my-theme);

The mixin mat.all-component-themes takes our theme object and generates all the necessary CSS for every Material component.

### Step 5: Include the Theme in angular.json

Finally, tell your Angular app to use your new theme file instead of a pre-built one.

// angular.json
"styles": [
  "src/custom-theme.scss", // <-- Add this
  "src/styles.scss"
],

Now, run ng serve, and you should see your app with a beautiful new Teal and Amber theme!


## Example: Changing Only Button Colors

What if you don't want to apply the theme globally? Maybe you just want a specific set of buttons to have a different color. Instead of using mat.all-component-themes, you can use component-specific mixins.

Let's say you want buttons inside a .special-section to use a different, "secondary" theme.

// src/custom-theme.scss

// ... (keep the primary theme setup from before) ...

// Define a secondary theme with different colors
$secondary-primary: mat.define-palette(mat.$deep-purple-palette);
$secondary-accent: mat.define-palette(mat.$lime-palette);
$secondary-theme: mat.define-light-theme((
  color: (
    primary: $secondary-primary,
    accent: $secondary-accent,
  )
));

// Apply the theme only to buttons within a specific class
.special-section {
  // Use the color mixin to apply only color styles
  @include mat.button-color($secondary-theme);
}

Now, any Material button inside an element with the special-section class will use the Deep Purple theme!

<button mat-raised-button color="primary">I am Teal</button>

<div class="special-section">
  <button mat-raised-button color="primary">I am Deep Purple!</button>
  <button mat-raised-button color="accent">I am Lime!</button>
</div>

## Understanding the @forward Rule

As your theming file grows, you might want to split it into multiple files. This is where @forward becomes essential.

The @forward rule makes mixins, functions, and variables from another Sass module available to be used from your module, effectively creating a public API for your styles.

Let's say you create a central _theming-api.scss file to manage all your Material imports.

// src/theming/_theming-api.scss

// Forwarding makes these members available to any file that `@use`s this one.
@forward '@angular/material' show mat-core, mat-define-palette, mat-define-light-theme, mat-button-color;

Now, in your custom-theme.scss, you can import everything from this single file instead of directly from @angular/material.

// src/custom-theme.scss
@use 'theming/theming-api' as mat;

// All the forwarded members are available on the `mat` namespace!
@include mat.mat-core();

$my-primary: mat.mat-define-palette(...);

This helps you create a clean, organized, and scalable theming architecture for large applications.

By mastering these tools, you can take full control of your application's appearance and ensure it perfectly matches your brand's identity. Go ahead and build something beautiful! ✨

If you read this far, tweet to the author to show them you care. Tweet a Thanks

More Posts

Debugging Angular Without Knowing the Codebase?

Sunny - Sep 10

You Can Be an Angular Contributor: A Guide to Your First Open-Source PR

Sunny - Aug 5

How to Integrate LinkedIn API in a Web App for Login and User Details

Sunny - Sep 30

Angular 20.2 Just Killed CSS Leaks: Are You Using IsolatedShadowDom Yet?

Sunny - Aug 31

Boost Your Web Apps with Angular: A Beginner’s Guide

test12345 - Aug 26
chevron_left