Skip to content

Latest commit

 

History

History
457 lines (350 loc) · 28.7 KB

material-3.md

File metadata and controls

457 lines (350 loc) · 28.7 KB

Material 3 Theming

What is Material 3

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.

How to use Material 3 in your app

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.

Defining your theme

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
  )
));

Customizing your colors

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.

Customizing your typography

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.

Customizing your density

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).

Applying your theme

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 as color, width, etc.

Using component color variants

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

Granular customizations with CSS custom properties

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;
}

Theme your own components using a Material 3 theme

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));
  }
}

Reading tonal palette colors

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:
  • primary
  • secondary
  • tertiary
  • error
  • neutral
  • neutral-variant
$hue The hue number to read within the palette. This can be any of the standard hues:
  • 0
  • 10
  • 20
  • 30
  • 40
  • 50
  • 60
  • 70
  • 80
  • 90
  • 95
  • 99
  • 100

Reading color roles

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:
  • primary
  • on-primary
  • primary-container
  • on-primary-container
  • primary-fixed
  • primary-fixed-dim
  • on-primary-fixed
  • on-primary-fixed-variant
  • secondary
  • on-secondary
  • secondary-container
  • on-secondary-container
  • secondary-fixed
  • secondary-fixed-dim
  • on-secondary-fixed
  • on-secondary-fixed-variant
  • tertiary
  • on-tertiary
  • tertiary-container
  • on-tertiary-container
  • tertiary-fixed
  • tertiary-fixed-dim
  • on-tertiary-fixed
  • on-tertiary-fixed-variant
  • error
  • on-error
  • error-container
  • on-error-container
  • surface-dim
  • surface
  • surface-bright
  • surface-container-lowest
  • surface-container-low
  • surface-container
  • surface-container-high
  • surface-container-highest
  • on-surface
  • on-surface-variant
  • outline
  • outline-variant
  • inverse-surface
  • inverse-on-surface
  • inverse-primary
  • scrim
  • shadow

Reading the theme type

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.

Reading typescale properties

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:
  • display-large
  • display-medium
  • display-small
  • headline-large
  • headline-medium
  • headline-small
  • title-large
  • title-medium
  • title-small
  • body-large
  • body-medium
  • body-small
  • label-large
  • label-medium
  • label-small
$property The CSS font property to get a value for. This can be one of the following CSS properties:
  • font (The CSS font shorthand, includes all font properties except letter-spacing)
  • font-family
  • font-size
  • font-weight
  • line-height
  • letter-spacing

Reading the density scale

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.

How to migrate an app from Material 2 to Material 3

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.

Update your components that use Angular Material themes to be compatible with Material 3

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.
  }
}

Pass a new M3 theme in your global theme styles

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.

Update usages of APIs that are not supported for Material 3 themes

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 in html { ... }
  • 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 the typography-hierarchy styles, as this would violate M3's guarantee to not add selectors. Instead, the typography-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.

(Optional) add backwards compatibility styles for color variants

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);
}

(Optional) add backwards compatibility styles for typography hierarchy

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);

FAQ

Can I depend on the CSS custom property names being stable?

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.

Are the Material 2 styles and APIs going away?

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.