Material 3 (M3) is the latest iteration of Google's open-source design system, Material Design. It is the successor to Material 2 (M2), the design system which Angular Material has followed.
M3 is implemented in Angular Material as an alternate Sass theme for the same set of Angular
Material components already used by many apps. To use M3 with Angular Material, create your theme
using the define-theme
function from @angular/material
, as opposed to the
define-light-theme
or define-dark-theme
from @angular/material
that are used to create M2
themes.
The simplest usage of the API, $theme: mat.define-theme()
defines a theme with default values.
However, like its M2 counterparts, 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 . |
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. |
There are a number of color palettes available in @angular/material
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();
// 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 (see the
M3 typography spec to learn more about
these terms):
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. |
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). |
Once you've created your theme, you can apply it using the same -theme
, -color
, -typography
,
-density
, and -base
mixins used to apply M2 themes (read more about these mixins in the
general theming guide). For M3 themes, these mixins
make some guarantees about the emitted styles. These guarantees do not apply when passing
M2 themes.
- The mixins emit properties under the exact selector you specify. They will not add to the selector or increase the specificity of the rule.
- The mixins only emit
CSS custom property declarations
(e.g.
--some-prop: xyz
). They do not emit any standard CSS properties such ascolor
,width
, etc.
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, 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 |
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;
}
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));
}
}
To read a
tonal palette color
from the theme, use the get-theme-color
function with three arguments:
Argument | Description |
---|---|
$theme |
The M3 theme to read from. |
$palette |
The name of the palette to read from. This can be any of the standard M3 palettes:
|
$hue |
The hue number to read within the palette. This can be any of the standard hues:
|
To read a color role, use get-theme-color
with two
arguments:
Argument | Description |
---|---|
$theme |
The M3 theme to read from. |
$role |
The name of the color role. This can be any of the M3 color roles:
|
To read the theme type (light
or dark
), call get-theme-type
with a single argument:
Argument | Description |
---|---|
$theme |
The M3 theme to read from. |
To read a typescale property from the
theme, call get-theme-typography
with three arguments:
Argument | Description |
---|---|
$theme |
The M3 theme to read from. |
$level |
The typescale level. This can be any of the M3 typescale levels:
|
$property |
The CSS font property to get a value for. This can be one of the following CSS properties:
|
To read the density scale (0
, -1
, -2
, -3
, -4
, or -5
) from the theme, call
get-theme-density
with a single argument:
Argument | Description |
---|---|
$theme |
The M3 theme to read from. |
Angular Material does not offer an automated migration from M2 to M3 because the design of your app is subjective. Material Design offers general principles and constraints to guide you, but ultimately it is up to you to decide how to apply those in your app. That said, Angular Material's M3 themes were designed with maximum compatibility in mind.
In order to facilitate a smooth transition from M2 to M3, it may make sense to have your components support both M2 and M3 themes. Once the entire app is migrated, the support for M2 themes can be removed.
The simplest way to accomplish this is by checking the theme version and emitting different styles
for M2 vs M3. You can check the theme version using the get-theme-version
function from
@angular/material
. The function will return 0
for an M2 theme or 1
for an M3 theme (see
theme your own components using a Material 3 theme
for how to read values from an M3 theme).
@use '@angular/material' as mat;
@mixin my-comp-theme($theme) {
@if (mat.get-theme-version($theme) == 1) {
// Add your new M3 styles here.
} @else {
// Keep your old M2 styles here.
}
}
Create a new M3 theme object using define-theme
and pass it everywhere you were previously passing
your M2 theme. All Angular Material mixins that take an M2 theme are compatible with M3 themes as
well.
Because Material 3 is implemented as an alternate theme for the same components used for Material 2, the APIs for both are largely the same. However, there are a few differences to be aware of:
- M3 expects that any
@include
of the-theme
,-color
,-typography
,-density
, or-base
mixins should be wrapped in a selector. If your app includes such an@include
at the root level, we recommend wrapping it inhtml { ... }
- M3 has a different API for setting the color variant of a component (see using component color variants for more).
- The
backgroundColor
property of<mat-tab-group>
is not supported, and should not be used with M3 themes. - The
appearance="legacy"
variant of<mat-button-toggle>
is not supported, and should not be used with M3 themes. - For M3 themes, calling
all-component-typographies
does not emit thetypography-hierarchy
styles, as this would violate M3's guarantee to not add selectors. Instead, thetypography-hierarchy
mixin must be explicitly called if you want these styles in your app. - The
typography-hierarchy
mixin outputs CSS class names that correspond to the names of M3 typescale levels rather than M2 typescale levels. If you were relying on the M2 classes to style your app, you may need to update the class names.
We recommend not relying on the color="primary"
, color="accent"
, or color="warn"
options
that are offered by a number of Angular Material components for M2 themes. However, if you want to
quickly update to M3 and are willing to accept the extra CSS generated for these variants, you can
enable backwards compatibility styles that restore the behavior of this API. Call the
color-variants-backwards-compatibility
mixin from @angular/material
with the M3 theme you want
to generate color variant styles for.
@use '@angular/material' as mat;
$theme: mat.define-theme();
html {
@include mat.all-component-themes($theme);
@include mat.color-variants-backwards-compatibility($theme);
}
Calling the typography-hierarchy
mixin with an M3 theme generates styles for CSS classes that
match the names of M3 typescale names (e.g. .mat-headline-large
) rather than ones that match M2
typescale names (.mat-headline-1
). If you were using the M2 class names in your app we recommend
updating all usages to one of the new class names. However, to make migration easier, the
typography-hierarchy
mixin does support emitting the old class names in addition to the new ones.
We have made a best effort to map the M2 classes to reasonable equivalents in M3. To enable these
styles, pass an additional argument $back-compat: true
to the mixin.
@use '@angular/material' as mat;
$theme: mat.define-theme();
@include mat.typography-hierarchy($theme, $back-compat: true);
We may make changes to the custom property names before moving the API out of experimental, but these changes would be accompanied by a schematic to find & replace the old name with the new name across your app.
Material 2 styles and their APIs will continue to be supported, and we do not have any immediate plans to deprecate them. We understand that it will take time for applications to switch to the latest Material 3 styles, and we want to provide enough time for migrations. When we do decide to remove these APIs, they will be marked as deprecated and continue to be supported in the following two major releases. As of now, they are not considered deprecated.