Free discovery callFree discovery call

Mastering Angular Material 19 (Material 3): Theme Setup and Component Styling

From base theme to component-level overrides  here’s how to do Material 3 theming properly.

DevelopmentLast updated: 15 Apr 20256 min read

By Dario Šoć

Angular 18 introduced full support for Material 3, using design tokens implemented as CSS custom properties. This lets developers style components without relying on deep selectors or high-specificity overrides.

With Angular Material 19, the theming system gets a new API that makes customizing your app's look and feel much simpler. You get a clean, structured way to define colors, typography, and component behavior.

In this post, I’ll walk through practical tips for setting up themes quickly, and handling both global and component-level style overrides.


Here's what I used for this:

  • @angular/cli: 19.2.7
  • @angular/material: 19.2.7
npm i -g @angular/cli
ng new angular-material-19 --style scss

When prompted:

Prompt Your Input
Do you want to enable Server-Side Rendering (SSR) and Static Site Generation? N
cd angular-material-19
ng add @angular/material

Next, choose:

Prompt Your Input
The package @angular/material@19.2.7 will be installed and executed.
Would you like to proceed? (Y/N)
Y
Choose a prebuilt theme name, or "custom" for a custom theme: Custom
Set up global Angular Material typography styles? (Y/N) Y

Nice — the Angular project is up and running. Now it’s time to define the theme.

You can stick with one of the predefined Material color palettes, or go custom if you want more control. The only required color is primary, while secondary, tertiary, error and neutral colors are optional but recommended for a more refined design, also specify path and type of file(css/scss).

To generate a custom palette, run:

ng generate @angular/material:theme-color

Define the Theme in styles.scss

Let's open the src/styles.scss file and define our theme.

@use '@angular/material' as mat;
// in case of using custom theme replace with the actual file path
@use './path/to/_theme-colors' as my-theme;

html {
	@include mat.theme((
		color: mat.$violet-palette,
		// or using custom theme:
		color: (
		  primary: my-theme.$primary-palette,
		  tertiary: my-theme.$tertiary-palette,
		),
		typography: Roboto,
		// or using typography map:
		typography: (
		  plain-family: Roboto, // most of the components text
    	  brand-family: Open Sans, // mostly for titles and headings
    	  bold-weight: 800,
    	  medium-weight: 400,
    	  regular-weight: 200,
        ),
		density: 0 // from 0 to -5
    ))
}

html, body { height: 100%; }
body { 
	font-family: Roboto, "Helvetica Neue", sans-serif;
}
* {
	box-sizing: border-box;
	margin: 0;
}

With the theme in place, let’s add light and dark mode support.

We’ll hook into system color variables to set default background and text colors — no manual toggling needed.

(We’ll cover more about overriding system variables a bit later.)

@use '@angular/material' as mat;

html {
	color-scheme: light dark; // add color-scheme css property
	@include mat.theme((
		color: mat.$violet-palette,
		typography: Roboto,
		density: 0
	), $overrides: (
		surface: light-dark(#fefbff, #211f21), // override system variable
		on-surface: light-dark(#1c1b1d, #e6e1e3), // override system variable
	));
}

html, body { height: 100%; }
body {
	// Add default background and text colors
	background: var(--mat-sys-surface); // using system variables
	color: var(--mat-sys-on-surface);
	font-family: Roboto, "Helvetica Neue", sans-serif;
}
* {
	box-sizing: border-box;
	margin: 0;
}

Angular Material System Variables

Angular Material components rely on a set of system variables — defined as CSS custom properties via the material.theme mixin.

They come in three flavors: colors, typography, and elevation.

These variables follow the Material Design 3 spec, giving you a solid foundation that’s flexible and easy to extend.

🎨 Colors system variables


Based on MD 3 color system.

Most commonly used color variable within Angular Material components:

Token CSS Variables Description
Primary
--mat-sys-primary
--mat-sys-on-primary
Most common color used by Angular Material. Used for the background of filled buttons, icon color of selected radio buttons, and outline of form fields.
Surface
--mat-sys-surface
--mat-sys-on-surface
Used for the background color of the app and most components such as dialogs, cards, and tables.
Error
--mat-sys-error
--mat-sys-on-error
Used for the background of badges and the text color of invalid form field inputs.
Outline
--mat-sys-outline
--mat-sys-outline-variant
Used for dividers and the border color of outlined form fields.

—-mat-sys- color variable is usually paired with —-mat-sys-on- color which is used for icons, text, and other visual elements placed on an —-mat-sys- background.

Here’s an example of color system variables in use:

body {
	background: var(--mat-sys-surface);
	color: var(--mat-sys-on-surface);
}

Besides these, there are additional color system variables.

🅰️ Typography system variables


Based on MD 3 typography system.

Material Design 3 defines five typography categories: body, display, headline, label, and title — each with three sizes: small, medium, and large.

Next, we’ll walk through a few examples of how to use these typography variables in practice.

Category CSS Variables Usage
Display
--mat-sys-display-small
--mat-sys-display-medium
--mat-sys-display-large
Largest text on screen, meant for short, high-impact content or numbers. Angular Material components currently don’t use these by default.
Headline
--mat-sys-headline-small
--mat-sys-headline-medium
--mat-sys-headline-large
For short, high-emphasis text. Example: Dialog headers use `--mat-sys-headline-small`.
Title
--mat-sys-title-small
--mat-sys-title-medium
--mat-sys-title-large
Medium-emphasis text. Examples: • `--mat-sys-title-small`: Table headers, tab labels • `--mat-sys-title-medium`: Expansion panel headers • `--mat-sys-title-large`: Toolbar titles
Body
--mat-sys-body-small
--mat-sys-body-medium
--mat-sys-body-large
For longer passages of text. Example: Dialog body text uses `--mat-sys-body-medium`.
Label
--mat-sys-label-small
--mat-sys-label-medium
--mat-sys-label-large
Smaller text for inline elements or component text. Example: Buttons use `--mat-sys-label-large`.

Using Angular Material typography system tokens recomended by Angular Material team:

h1 {
	font: var(--mat-sys-display-large);
}
h2 {
	font: var(--mat-sys-display-medium);
}

You can customize any typography system variable by appending keywords like font, line-height, size, tracking, or weight.

That said, directly overriding these system variables isn’t recommended.

I’ll show you the cleaner, more flexible approach using a mixin a bit later in the post.

🏔️ Elevation system variables


Based on MD 3 elevation system.

Material Design defines six elevation levels to help create depth and visual hierarchy in your UI.

Elevation CSS Variables Usage
Level
--mat-sys-level0
--mat-sys-level1
--mat-sys-level2
--mat-sys-level3
--mat-sys-level4
--mat-sys-level5
Example: --mat-sys-level3 is used for the box-shadow of a FAB button.

Angular material tokens

To override tokenized styles, Angular Material gives you two powerful tools: system tokens and component tokens.

System Tokens


You can override system variables in two ways:

  1. Using the mat-theme-overrides mixin
  2. Passing an $overrides map directly into the mat.theme() definition

Both approaches work — it really comes down to personal preference.

Option 1: mat-theme-overrides

@include mat.theme-overrides((
  surface: light-dark(#fefbff, #211f21),
	on-surface: light-dark(#1c1b1d, #e6e1e3),
	display-large: 500 3.5rem/4rem Arial,
	level3: 0 4px 6px 1px var(--mat-sys-secodary)
));

Option 2: Overrides inside mat.theme()

@include mat.theme((
	color: mat.$violet-palette,
	typography: Roboto,
	density: 0
), $overrides: (
	surface: light-dark(#fefbff, #211f21), // --mat-sys-surface
	on-surface: light-dark(#1c1b1d, #e6e1e3), // --mat-sys-on-surface
	display-large: 500 3.5rem/4rem Arial, // --mat-sys-display-large
	level3: 0 4px 6px 1px var(--mat-sys-secodary) // --mat-sys-level0
));

Component Tokens


Each Angular Material component exposes an override mixin that lets you tweak token-based styles — including color, typography, and density.

You’ll find the full override API for each component in the Angular Material docs, under the “Styling” tab (new in v19).

Here’s a quick example using the button override API for mat-flat-button — and you can explore the full list of button tokens here.

@use '@angular/material' as mat;

// Customize the entire application by targeting :root. If you prefer to scope
// the style, user desired selector or style file.
:root {
  @include mat.button-overrides((
	// background and label color
    filled-container-color: light-dark(#082234, #775c89),
    filled-label-text-color: #FFFFFF,
    // disabled background and label color
    filled-disabled-container-color: light-dark(#08223480, #775c8980), 
    filled-disabled-label-text-color: light-dark(#FFFFFF, #A8ACB1),
    // label size
    filled-label-text-size: 14px,
    // color used for hover, focus and active state of button
    filled-state-layer-color: light-dark(#475A66, #8f719d),
    // opacity for button hover state
	filled-hover-state-layer-opacity: 1,
  ));
}

That’s a wrap on theming (for now)

With Angular 19 and full Material 3 support, customizing your app’s design is smoother and more flexible than ever. The new theming APIs — along with system and component tokens — give you the control to build consistent, polished UIs without messy CSS overrides.

In the next post, I’ll dig into advanced button styling: how to override tokens for different variants, handle states like hover and disabled, and apply consistent design patterns across your app.

Got feedback or want to share how you're using Material 3 theming? Drop us a note at hello@prototyp.digital.

Happy theming! 🎨

Related ArticlesTechnology x Design

View all articlesView all articles
( 01 )Get started

Start a Project