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:
- 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.
- Typography: Configuration for font families, sizes, and weights.
- 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! ✨