Angular Material's theming system lets you customize base, color, typography, and density styles for components in your application. The theming system is based on Google's Material Design 3 specification which is the latest iteration of Google's open-source design system, Material Design.
For Material 2 specific documentation and how to update to Material 3, see the Material 2 guide.
This document describes the concepts and APIs for customizing colors. For typography customization, see Angular Material Typography. For guidance on building components to be customizable with this system, see Theming your own components.
Angular Material's theming APIs are built with Sass. This document assumes familiarity with CSS and Sass basics, including variables, functions, and mixins.
A theme file is a Sass file that calls Angular Material Sass mixins to output color, typography, and density CSS styles.
core
mixin
Angular Material defines a mixin named core
that includes prerequisite styles for common
features used by multiple components, such as ripples. The core
mixin must be included exactly
once for your application, even if you define multiple themes. Including the core
mixin multiple
times will result in duplicate CSS in your application.
@use '@angular/material' as mat;
@include mat.core();
Angular Material represents a theme as a Sass map that contains your color, typography, and density choices, as well as some base design system settings.
The simplest usage of the API, $theme: mat.define-theme()
defines a theme with default values.
However, define-theme
allows you to configure the appearance of your
Angular Material app along three theming dimensions: color, typography, and density, by passing a
theme configuration object. The configuration object may have the following properties.
Property | Description |
---|---|
color |
[Optional] A map of color options. See customizing your colors for details. |
typography |
[Optional] A map of typography options. See customizing your typography for details. |
density |
[Optional] A map of density options. See customizing your density for details. |
@use '@angular/material' as mat;
$theme: mat.define-theme((
color: (
theme-type: dark,
primary: mat.$violet-palette,
),
typography: (
brand-family: 'Comic Sans',
bold-weight: 900
),
density: (
scale: -1
)
));
The following aspects of your app's colors can be customized via the color
property of the theme
configuration object (see the M3 color spec to learn
more about these terms):
Color Property | Description |
---|---|
theme-type |
[Optional] Specifies the type of theme, light or dark . The choice of a light versus a dark theme determines the background and foreground colors used throughout the components. |
primary |
[Optional] Specifies the palette to use for the app's primary color palette. (Note: the secondary, neutral, and neutral-variant palettes described in the M3 spec will be automatically chosen based on your primary palette, to ensure a harmonious color combination). |
tertiary |
[Optional] Specifies the palette to use for the app's tertiary color palette. |
Angular Material includes several pre-built theme CSS files, each with different palettes selected. You can use one of these pre-built themes if you don't want to define a custom theme with Sass.
Theme | Light or dark? | Specification |
---|---|---|
azure-blue.css |
Light | Material Design 3 |
rose-red.css |
Light | Material Design 3 |
cyan-orange.css |
Dark | Material Design 3 |
magenta-violet.css |
Dark | Material Design 3 |
deeppurple-amber.css |
Light | Material Design 2 |
indigo-pink.css |
Light | Material Design 2 |
pink-bluegrey.css |
Dark | Material Design 2 |
purple-green.css |
Dark | Material Design 2 |
These files include the CSS for every component in the library. To include only the CSS for a subset of components, you must use the Sass API detailed in Defining a theme above. You can reference the source code for these pre-built themes to see examples of complete theme definitions.
The pre-built themes are based on a set of pre-defined palettes that can be used with the primary
and tertiary
options:
$red-palette
$green-palette
$blue-palette
$yellow-palette
$cyan-palette
$magenta-palette
$orange-palette
$chartreuse-palette
$spring-green-palette
$azure-palette
$violet-palette
$rose-palette
Alternatively, a theme can be generated with a custom color with the following schematic:
ng generate @angular/material:m3-theme
This schematic integrates with Material Color Utilities to build a theme based on a generated set of palettes based on a single color. Optionally you can provide additional custom colors for the secondary, tertiary, and neutral palettes.
The output of the schematic is a new Sass file that exports a theme or themes (if generating both a light and dark theme) that can be provided to component theme mixins.
@use '@angular/material' as mat;
@use './path/to/m3-theme';
@include mat.core();
html {
// Apply the light theme by default
@include mat.core-theme(m3-theme.$light-theme);
@include mat.button-theme(m3-theme.$light-theme);
}
Learn more about this schematic in its documentation.
The following aspects of your app's typography can be customized via the typography
property of
the theme configuration object.
Typography Property | Description |
---|---|
plain-family |
[Optional] The font family to use for plain text, such as body text. |
brand-family |
[Optional] The font family to use for brand text, such as headlines. |
bold-weight |
[Optional] The font weight to use for bold text. |
medium-weight |
[Optional] The font weight to use for medium text. |
regular-weight |
[Optional] The font weight to use for regular text. |
See the typography guide for more information.
The following aspects of your app's density can be customized via the density
property of the
theme configuration object:
Density Property | Description |
---|---|
scale |
[Optional] The level of compactness of the components in your app, from 0 (most space) to -5 (most compact). |
The core-theme
Sass mixin emits prerequisite styles for common features used by multiple
components, such as ripples. This mixin must be included once per theme.
Each Angular Material component has a mixin for each theming dimension: base,
color, typography, and density. For example, MatButton
declares button-base
, button-color
,
button-typography
, and button-density
. Each mixin emits only the styles corresponding to that
dimension of customization.
Additionally, each component has a "theme" mixin that emits all styles that depend on the theme
config. This theme mixin only emits color, typography, or density styles if you provided a
corresponding configuration to define-theme
, and it always emits the base styles.
Once you've created your theme, you can apply it using the same -theme
, -color
, -typography
, -density
, and -base
mixins.
For M3 themes, these mixins make some guarantees about the emitted styles.
--some-prop: xyz
). They do not emit any standard CSS properties such as color
,
width
, etc.Apply the styles for each of the components used in your application by including each of their theme Sass mixins.
@use '@angular/material' as mat;
@include mat.core();
$my-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette,
),
));
html {
// Emit theme-dependent styles for common features used across multiple components.
@include mat.core-theme($my-theme);
// Emit styles for MatButton based on `$my-theme`. Because the configuration
// passed to `define-theme` omits typography, `button-theme` will not
// emit any typography styles.
@include mat.button-theme($my-theme);
// Include the theme mixins for other components you use here.
}
As an alternative to listing every component that your application uses, Angular Material offers
Sass mixins that includes styles for all components in the library: all-component-bases
,
all-component-colors
, all-component-typographies
, all-component-densities
, and
all-component-themes
. These mixins behave the same as individual component mixins, except they
emit styles for core-theme
and all 35+ components in Angular Material. Unless your application
uses every single component, this will produce unnecessary CSS.
@use '@angular/material' as mat;
@include mat.core();
$my-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette,
),
));
html {
@include mat.all-component-themes($my-theme);
}
To include the emitted styles in your application, add your theme file to the styles
array of
your project's angular.json
file.
Angular Material themes are divided along four dimensions: base, color, typography, and density.
Common base styles for the design system. These styles don't change based on your configured
colors, typography, or density, so they only need to be included once per application. These
mixins include structural styles such as border-radius, border-width, etc. All components have a base
mixin that can be used to include its base styles. (For example,
@include mat.checkbox-base($theme)
)
Styles related to the colors in your application. These style should be included at least once in
your application. Depending on your needs, you may need to include these styles multiple times
with different configurations. (For example, if your app supports light and dark theme colors.)
All components have a color mixin that can be used to include its color styles. (For example,
@include mat.checkbox-color($theme)
)
Styles related to the fonts used in your application, including the font family, size, weight,
line-height, and letter-spacing. These style should be included at least once in your application.
Depending on your needs, you may need to include these styles multiple times with different
configurations. (For example, if your app supports reading content in either a serif or sans-serif
font.) All components have a typography mixin that can be used to include its typography
styles. (For example, @include mat.checkbox-typography($theme)
)
Styles related to the size and spacing of elements in your application. These style should be
included at least once in your application. Depending on your needs, you may need to include these
styles multiple times with different configurations. (For example, if your app supports both a
normal and compact mode). All components have a density mixin that can be used to include its
density styles. (For example, @include mat.checkbox-density($theme)
)
All components also support a theme mixin that can be used to include the component's styles for all
theme dimensions at once. (For example, @include mat.checkbox-theme($theme)
).
The recommended approach is to rely on the theme
mixins to lay down your base styles, and if
needed use the single dimension mixins to override particular aspects for parts of your app (see the
section on Multiple themes in one file.)
Using the Sass API described in Defining a theme, you can also define multiple themes by repeating the API calls multiple times. You can do this either in the same theme file or in separate theme files.
Defining multiple themes in a single file allows you to support multiple themes without having to manage loading of multiple CSS assets. The downside, however, is that your CSS will include more styles than necessary.
To control which theme applies when, @include
the mixins only within a context specified via
CSS rule declaration. See the documentation for Sass mixins for further background.
@use '@angular/material' as mat;
@include mat.core();
// Define a dark theme
$dark-theme: mat.define-theme((
color: (
theme-type: dark,
primary: mat.$violet-palette,
),
));
// Define a light theme
$light-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette,
),
));
html {
// Apply the dark theme by default
@include mat.core-theme($dark-theme);
@include mat.button-theme($dark-theme);
// Apply the light theme only when the user prefers light themes.
@media (prefers-color-scheme: light) {
// Use the `-color` mixins to only apply color styles without reapplying the same
// typography and density styles.
@include mat.core-color($light-theme);
@include mat.button-color($light-theme);
}
}
You can define multiple themes in separate files by creating multiple theme files per
Defining a theme, adding each of the files to the styles
of your
angular.json
. However, you must additionally set the inject
option for each of these files to
false
in order to prevent all the theme files from being loaded at the same time. When setting
this property to false
, your application becomes responsible for manually loading the desired
file. The approach for this loading depends on your application.
By default, Angular Material does not apply any styles to your DOM outside its own components. If you want to set your application's background color to match the components' theme, you can either:
mat-sidenav-container
, assuming you're using
MatSidenav
, ormat-app-background
CSS class to your main content root element (typically body
).The CSS custom properties emitted by the theme mixins are derived from
M3's design tokens. To further
customize your UI beyond the define-theme
API, you can manually set these custom properties in
your styles.
The guarantees made by the theme mixins mean that you do not need to target internal selectors of
components or use excessive specificity to override any of these tokenized properties. Always apply
your base theme to your application's root element (typically html
or body
) and apply any
overrides on the highest-level selector where they apply.
<mat-sidenav-container>
Some content...
<mat-sidenav>
Some sidenav content...
<mat-checkbox class="danger">Enable admin mode</mat-checkbox>
</mat-sidenav>
</mat-sidenav-container>
@use '@angular/material' as mat;
$light-theme: mat.define-theme();
$dark-theme: mat.define-theme((
color: (
theme-type: dark
)
));
html {
// Apply the base theme at the root, so it will be inherited by the whole app.
@include mat.all-component-themes($light-theme);
}
mat-sidenav {
// Override the colors to create a dark sidenav.
@include mat.all-component-colors($dark-theme);
}
.danger {
// Override the checkbox hover state to indicate that this is a dangerous setting. No need to
// target the internal selectors for the elements that use these variables.
--mdc-checkbox-unselected-hover-state-layer-color: red;
--mdc-checkbox-unselected-hover-icon-color: red;
}
Angular Material's density customization is based on the Material Design density guidelines. This system defines a scale where zero represents the default density. You can decrement the number for more density and increment the number for less density.
The density system is based on a density scale. The scale starts with the
default density of 0
. Each whole number step down (-1
, -2
, etc.) reduces
the affected sizes by 4dp
, down to the minimum size necessary for a component to render
coherently.
Components that appear in task-based or pop-up contexts, such as MatDatepicker
, don't change their
size via the density system. The Material Design density guidance explicitly
discourages increasing density for such interactions because they don't compete for space in the
application's layout.
You can apply custom density setting to the entire library or to individual components using their density Sass mixins.
// You can set a density setting in your theme to apply to all components.
$dark-theme: mat.define-theme((
color: ...,
typography: ...,
density: (
scale: -2
),
));
// Or you can selectively apply the Sass mixin to affect only specific parts of your application.
.the-dense-zone {
@include mat.button-density(-1);
}
By default, most components indicate browser focus by changing their background color as described by the Material Design specification. This behavior, however, can fall short of accessibility requirements, such as WCAG, which require a stronger indication of browser focus.
Angular Material supports rendering highly visible outlines on focused elements. Applications can
enable these strong focus indicators via two Sass mixins:
strong-focus-indicators
and strong-focus-indicators-theme
.
The strong-focus-indicators
mixin emits structural indicator styles for all components. This mixin
should be included exactly once in an application, similar to the core
mixin described above.
The strong-focus-indicators-theme
mixin emits only the indicator's color styles. This mixin should
be included once per theme, similar to the theme mixins described above. Additionally, you can use
this mixin to change the color of the focus indicators in situations in which the default color
would not contrast sufficiently with the background color.
The following example includes strong focus indicator styles in an application alongside the rest of the custom theme API.
@use '@angular/material' as mat;
@include mat.core();
@include mat.strong-focus-indicators();
$my-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette,
),
));
html {
@include mat.all-component-themes($my-theme);
@include mat.strong-focus-indicators-theme($my-theme);
}
You can pass a configuration map to strong-focus-indicators
to customize the appearance of the
indicators. This configuration includes border-style
, border-width
, and border-radius
.
You also can customize the color of indicators with strong-focus-indicators-theme
. This mixin
accepts either a theme, as described earlier in this guide, or a CSS color value. When providing a
theme, the indicators will use the default hue of the primary palette.
The following example includes strong focus indicator styles with custom settings alongside the rest of the custom theme API.
@use '@angular/material' as mat;
@include mat.core();
@include mat.strong-focus-indicators((
border-style: dotted,
border-width: 4px,
border-radius: 2px,
));
$my-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette,
),
));
html {
@include mat.all-component-themes($my-theme);
@include mat.strong-focus-indicators-theme(purple);
}
Angular Material assumes that, by default, all theme styles are loaded as global CSS. If you want to use Shadow DOM in your application, you must load the theme styles within each shadow root that contains an Angular Material component. You can accomplish this by manually loading the CSS in each shadow root, or by using Constructable Stylesheets.
Angular Material does not apply styles based on user preference media queries, such as
prefers-color-scheme
or prefers-contrast
. Instead, Angular Material's Sass mixins give you the
flexibility to apply theme styles to based on the conditions that make the most sense for your
users. This may mean using media queries directly or reading a saved user preference.
A number of components have a color
input property that allows developers to apply different color
variants of the component. When using an M3 theme, this input still adds a CSS class to the
component (e.g. .mat-accent
). However, there are no built-in styles targeting these classes. You
can instead apply color variants by passing the $color-variant
option to a component's -theme
or
-color
mixins.
<mat-checkbox class="tertiary-checkbox" />
<section class="tertiary-checkbox">
<mat-checkbox />
</section>
@use '@angular/material' as mat;
$theme: mat.define-theme();
.tertiary-checkbox {
@include mat.checkbox-color($theme, $color-variant: tertiary);
}
This API is more flexible, and produces less CSS. For example, the .tertiary-checkbox
class shown
above can be applied to any checkbox or any element that contains checkboxes, to change the color
of all checkboxes within that element.
While you should prefer applying the mixins with color variants explicitly, if migrating from M2 to
M3 you can alternatively use the provided backwards compatibility mixins
that apply styles directly to the existing CSS classes (mat-primary
, mat-accent
, and
mat-warn
).
The table below shows the supported $color-variant
values for each component. (Unlisted components
do not support any color variants.)
Component | Supported $color-variant values |
Default |
---|---|---|
Badge | primary , secondary , tertiary , error |
error |
Button | primary , secondary , tertiary , error |
primary |
Button-toggle | primary , secondary , tertiary , error |
secondary |
Checkbox | primary , secondary , tertiary , error |
primary |
Chips | primary , secondary , tertiary , error |
secondary |
Datepicker | primary , secondary , tertiary , error |
primary |
Fab | primary , secondary , tertiary |
primary |
Form-field | primary , secondary , tertiary , error |
primary |
Icon | surface , primary , secondary , tertiary , error |
surface |
Option | primary , secondary , tertiary , error |
secondary |
Progress-bar | primary , secondary , tertiary , error |
primary |
Progress-spinner | primary , secondary , tertiary , error |
primary |
Pseudo-checkbox | primary , secondary , tertiary , error |
primary |
Radio | primary , secondary , tertiary , error |
primary |
Select | primary , secondary , tertiary , error |
primary |
Slide-toggle | primary , secondary , tertiary , error |
primary |
Slider | primary , secondary , tertiary , error |
primary |
Stepper | primary , secondary , tertiary , error |
primary |
Tabs | primary , secondary , tertiary , error |
primary |
Angular Material supports customizing color, typography, and density as outlined in this document. Angular strongly discourages, and does not directly support, overriding component CSS outside the theming APIs described above. Component DOM structure and CSS classes are considered private implementation details that may change at any time.
The same utility functions for reading properties of M2 themes (described in our guide for theming your components) can be used to read properties from M3 themes. However, the named palettes, typography levels, etc. available are different for M3 themes, in accordance with the spec.
The structure of the theme object is considered an implementation detail. Code should not depend on
directly reading properties off of it, e.g. using map.get
. Always use the utility functions
provided by Angular Material to access properties of the theme.
@use '@angular/material' as mat;
@mixin my-comp-theme($theme) {
.my-comp {
font: mat.get-theme-typography($theme, body-large, font);
letter-spacing: mat.get-theme-typography($theme, body-large, letter-spacing);
background: mat.get-theme-color($theme, surface);
@if mat.get-theme-type($theme) == dark {
color: mat.get-theme-color($theme, primary, 20);
} @else {
color: mat.get-theme-color($theme, primary, 80);
}
padding: 48px + (2px * mat.get-theme-density($theme));
}
}