Angular Material 3 自定义主题

1. 什么是 Material 3

Material 3 (M3)是 Google 开源设计系统 Material Design 的最新版本。它是 Angular Material 所遵循的设计系统 Material 2 (M2)的继承者。

从 v17.2.0 开始,Angular Material 除了 M2 之外还包括对 M3 样式的实验性支持。该团队计划在短暂的实验后稳定对 M3 的支持,以获得有关设计和 API 的反馈。

2. 如何在您的应用中使用 Material 3

作为许多应用程序已使用的同一组 Angular Material 组件的备用 Sass 主题。要将 M3 与 Angular Material 结合使用,请使用函数@angular/material-experimental 包中的 define-theme 创建主题,而不是 使用 @angular/material 的 define-light-theme 或 define-dark-theme 用于创建 M2 主题。

2.1. 定义您的主题

API 最简单的用法$theme: matx.define-theme()是定义具有默认值的主题。但是,与 M2 对应项一样,define-theme 允许您通过传递主题配置对象,沿着三个主题维度配置 Angular Material 应用程序的外观:颜色、排版和密度。配置对象可以具有以下属性。

属性描述
color[可选] 颜色选项。有关详细信息,请参阅自定义颜色
typography[可选] 颜色选项。有关详细信息,请参阅自定义排版
density[可选] 密度选项。有关详细信息,请参阅自定义密度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@use "@angular/material-experimental" as matx;

$theme: matx.define-theme(
(
color: (
theme-type: dark,
primary: matx.$m3-violet-palette,
),
typography: (
brand-family: "Comic Sans",
bold-weight: 900,
),
density: (
scale: -1,
),
)
);

2.2. 定制您的颜色

您的应用程序颜色的以下方面可以通过 color 主题配置对象的属性进行自定义(请参阅M3 颜色规范以了解有关这些术语的更多信息):

颜色属性描述
theme-type[可选] 指定主题的类型,light 或 dark.
primary[可选] 指定用于应用程序主要调色板的调色板。 (注意:M3 规范中描述的辅助调色板、中性调色板和中性变体调色板将根据您的主调色板自动选择,以确保和谐的颜色组合)。
tertiary[可选] 指定用于应用程序的第三调色板的调色板。

有许多可用的调色板@angular/material-experimental 可以与 primary 和 tertiary 选项一起使用:

  • $m3-red-palette 红色
  • $m3-green-palette 绿色
  • $m3-blue-palette 蓝色
  • $m3-yellow-palette 黄色
  • $m3-cyan-palette 青色主题
  • $m3-magenta-palette 洋红色
  • $m3-orange-palette 橙色
  • $m3-chartreuse-palette 浅黄色/浅绿色
  • $m3-azure-palette 天蓝色的/蔚蓝色的
  • $m3-violet-palette 蓝紫色/紫罗兰色
  • $m3-rose-palette 玫红色

2.3. 定制 typography

您的应用程序排版的以下方面可以通过 typography 主题配置对象的属性进行自定义(请参阅 M3 排版规范以了解有关这些术语的更多信息):

版式属性描述
plain-family[可选] 用于纯文本(例如正文)的字体系列。
brand-family[可选] 用于品牌文本(例如标题)的字体系列。
bold-weight[可选] 用于粗体文本的字体粗细。
medium-weight[可选] 用于中等文本的字体粗细。
regular-weight[可选] 用于常规文本的字体粗细。

2.4. 定制密度

您的应用程序密度的以下方面可以通过 density 主题配置对象的属性进行自定义:

密度特性描述
scale[可选] 应用程序中组件的紧凑程度,从 0(最多空间)到-5(最紧凑)。

3. 应用主题

创建主题后,您可以使用与应用 M2 相同的-theme、-color、-typography、 -density 以及 -base mixin 来应用主题(在主题通用指南中了解有关这些 mixins 的更多信息)。对于 M3 主题,这些 mixins 对生成的样式做出了一些保证。这些保证对 M2 主题时不适用。

mixins 在您指定的确切选择器下生成属性。它们不会被添加到选择器或增加规则的特殊性。
mixin 只生成 CSS 自定义属性声明 (例如–some-prop: xyz)。它们不发出任何标准 CSS 属性,例如 color、 width 等。

3.1. 使用组件颜色变体

许多组件都有一个 color 属性,允许开发人员应用组件的不同颜色变体。当使用 M3 主题时,此属性仍然向组件添加 CSS 类(例如.mat-accent)。但是,没有针对这些类的内置样式。您可以通过将$color-variant 选项传递给组件-theme 或 -color mixin 来应用颜色变体。

1
2
3
4
<mat-checkbox class="tertiary-checkbox" />
<section class="tertiary-checkbox">
<mat-checkbox />
</section>
1
2
3
4
5
6
7
8
@use "@angular/material" as mat;
@use "@angular/material-experimental" as matx;

$theme: matx.define-theme();

.tertiary-checkbox {
@include mat.checkbox-color($theme, $color-variant: tertiary);
}

此 API 更灵活,并且生成的 CSS 更少。例如,.tertiary-checkbox 上面显示的类可以应用于任何复选框或包含复选框的任何元素,以更改该元素内所有复选框的颜色。

虽然您应该更喜欢显式应用具有颜色变体的 mixins,但您也可以使用 mixins 提供的向后兼容性 ,将样式直接应用于现有 CSS 类(mat-primary、mat-accent 和 mat-warn)。

下表显示了$color-variant 每个组件支持的值。 (未列出的组件不支持任何颜色变体。)

组件支持的$color-variant 值默认
Badge 徽章primary, secondary, tertiary,errorerror
Button 按钮primary, secondary, tertiary,errorprimary
Button-toggleprimary, secondary, tertiary,errorsecondary
Checkbox 复选框primary, secondary, tertiary,errorprimary
Chipsprimary, secondary, tertiary,errorsecondary
Datepicker 日期选择器primary, secondary, tertiary,errorprimary
Fabprimary, secondary,tertiaryprimary
Form-fieldprimary, secondary, tertiary,errorprimary
Icon 图标surface, primary, secondary, tertiary,errorsurface
Option 选项primary, secondary, tertiary,errorsecondary
Progress-bar 进度条primary, secondary, tertiary,errorprimary
Progress-spinnerprimary, secondary, tertiary,errorprimary
Pseudo-checkboxprimary, secondary, tertiary,errorprimary
Radio 单选框primary, secondary, tertiary,errorprimary
Selectprimary, secondary, tertiary,errorprimary
Slide-toggleprimary, secondary, tertiary,errorprimary
Slideprimary, secondary, tertiary,errorprimary
Stepperprimary, secondary, tertiary,errorprimary
Tabsprimary, secondary, tertiary,errorprimary

3.2. 使用 CSS 自定义属性进行精细自定义

主题 mixin 生成的 CSS 自定义属性源自 M3 的设计令牌。要在 API 之外进一步自定义 UI define-theme,您可以在样式中手动设置这些自定义属性。

主题 mixin 做出的保证意味着您不需要以组件的内部选择器为目标,也不需要使用过多的特异性来覆盖任何这些标记化属性。始终将基本主题应用到应用程序的根元素(通常为 html 或 body),并将任何覆盖应用到适用的最高级别选择器上。

1
2
3
4
5
6
7
<mat-sidenav-container>
Some content...
<mat-sidenav>
Some sidenav content...
<mat-checkbox class="danger">Enable admin mode</mat-checkbox>
</mat-sidenav>
</mat-sidenav-container>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@use "@angular/material" as mat;
@use "@angular/material-experimental" as matx;

$light-theme: matx.define-theme();
$dark-theme: matx.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;
}

4. 使用 Material 3 主题为您自己的组件设置主题

用于读取 M2 主题属性的相同实用程序函数(在 我们的组件主题化指南中描述)可用于从 M3 主题读取属性。然而,根据规范,M3 主题的可用命名调色板、排版级别等有所不同。

主题对象的结构被视为实现细节。代码不应依赖于直接读取其属性,例如使用 map.get.始终使用 Angular Material 提供的实用函数来访问主题的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@use "@anuglar/material" as mat;
@use "@anuglar/material-experimental" as matx;

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

4.1. 读取色调调色板颜色

要从主题中读取 色调调色板颜色 get-theme-color,请使用带有三个参数的函数:

参数描述
$theme要读取的 M3 主题。
$palette要读取的调色板的名称。这可以是任何标准 M3 调色板:
primary
secondary
tertiary
error
neutral
neutral-variant
$hue在调色板中读取的色相编号。这可以是任何标准色调:
0
10
20
30
40
50
60
70
80
90
95
99
100

4.2. 解读色彩角色

要读取颜色角色,请 使用 get-theme-color 与两个参数一起使用:

参数描述
$theme要读取的 M3 主题。
$role颜色角色的名称。这可以是任何 M3 颜色角色:
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

4.3. 读取主题类型

要读取主题类型(light 或 dark),请 使用 get-theme-type 并存入一个参数进行调用:

参数描述
$theme要读取的 M3 主题。

4.4. 读取类型比例属性

要从主题读取 typescale 请使用 get-theme-typography 方法,并传入三个参数进行调用:

参数描述
$theme要读取的 M3 主题。
$level字体级别。这可以是任何 M3 类型级别:
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要获取值的 CSS 字体属性。这可以是以下 CSS 属性之一:
font(CSS 字体简写,包括除字母间距之外的所有字体属性)
font-family
font-size
font-weight
line-height
letter-spacing

4.5. 读取密度标尺

要从主题 读取密度标度(0、-1、-2、-3、-4 或 -5),请使用单个参数进行调用:get-theme-density

| 参数 | 描述 |
| $theme | 要读取的 M3 主题。|

5. 如何将应用程序从 Material 2 迁移到 Material 3

Angular Material 不提供从 M2 到 M3 的自动迁移,因为应用程序的设计是主观的。 Material Design 提供了一般原则和约束来指导您,但最终由您决定如何在您的应用程序中应用这些原则和约束。也就是说,Angular Material 的 M3 主题在设计时就考虑到了最大兼容性。

5.1. 更新使用 Angular Material 主题的组件以与 Material 3 兼容

为了促进从 M2 到 M3 的平滑过渡,让您的组件同时支持 M2 和 M3 主题可能是有意义的。迁移整个应用程序后,可以删除对 M2 主题的支持。

实现此目的的最简单方法是检查主题版本并为 M2 和 M3 发出不同的样式。您可以使用 的 get-theme-version 功能 检查主题版本@angular/material。该函数将返回 0M2 主题或 1M3 主题(请参阅 使用 Material 3 主题主题您自己的组件, 了解如何从 M3 主题读取值)。

1
2
3
4
5
6
7
8
9
@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.
}
}

5.2. 在您的全局主题样式中传递新的 M3 主题

使用创建一个新的 M3 主题对象 define-theme 并将其传递到您之前传递 M2 主题的任何地方。所有采用 M2 主题的 Angular Material mixins 也与 M3 主题兼容。

5.3. 更新 Material 3 主题不支持的 API

由于 Material 3 是作为 Material 2 所用相同组件的替代主题实现的,因此两者的 API 基本相同。但是,有一些差异需要注意:

  • M3 期望任何@include、-theme、-color、-typography 或-densitymixin-base 都应包装在选择器中。如果您的应用程序@include 在根级别包含这样的内容,我们建议将其包装在 html { … }
  • M3 有一个不同的 API 用于设置组件的颜色变体(有关更多信息,请参阅 使用组件颜色变体)。
  • 不支持 backgroundColor 属性,并且不应与 M3 主题一起使用。
  • 不支持 appearance=”legacy” 变量,并且不应与 M3 主题一起使用。
  • 对于 M3 主题,调用 all-component-typographies 不会生成样式 typography-hierarchy ,因为这会违反 M3 不添加选择器的保证。相反, 如果您希望在应用程序中使用 typography-hierarchy 的这些样式,则必须显式调用 mixin。
  • mixintypography-hierarchy 输出对应于 M3 字体级别而不是 M2 字体级别名称的 CSS 类名称。如果您依赖 M2 类来设计应用程序的样式,则可能需要更新类名称。

5.4. 为颜色变体添加向后兼容样式(可选)

我们建议不要依赖许多 Angular Material 组件提供的的 color=”primary”、color=”accent”或 color=”warn” M2 主题选项。但是,如果您想快速更新到 M3 并愿意接受为这些变体生成的额外 CSS,您可以启用向后兼容样式来恢复此 API 的行为。使用您想要为其生成颜色变体样式的 M3 主题调用 @angular/material-experimental
的 color-variants-back-compat mixin 。

1
2
3
4
5
6
7
8
9
@use "@angular/material" as mat;
@use "@angular/material-experimental" as matx;

$theme: matx.define-theme();

html {
@include mat.all-component-themes($theme);
@include matx.color-variants-back-compat($theme);
}

5.5. 为排版层次结构添加向后兼容样式(可选)

使用 M3 主题调用 typography-hierarchy mixin 会生成与 M3 typescale 名称(例如.mat-headline-large)相匹配的 CSS 类样式,而不是与 M2 类型规模名称匹配的 CSS 类样式(.mat-headline-1)。如果您在应用程序中使用 M2 类名称,我们建议将所有用法更新为新类名称。然而,为了使迁移更容易, typography-hierarchy mixin 除了新的类名之外还支持生成旧的类名。我们已尽最大努力将 M2 类映射到 M3 中合理的等效项。要启用这些样式,请将附加参数$back-compat: true 传递 给 mixin。

1
2
3
4
5
6
@use "@angular/material" as mat;
@use "@angular/material-experimental" as matx;

$theme: matx.define-theme();

@include mat.typography-hierarchy($theme, $back-compat: true);

5.6. 常问问题

  1. 我可以使用预定义的 Material 3 调色板以外的颜色吗?

    目前,我们仅提供预定义的调色板,但我们计划添加对使用自定义生成的调色板的支持.

  2. 我可以依赖稳定的 CSS 自定义属性名称吗?

    在将 Material 3 API 走出实验阶段之前,我们可能会对自定义属性名称进行更改,但伴随着这些更改我们将提供相应的 schematic,以便在您的应用程序中方便的替换旧名称为新名称。

  3. Material 2 样式和 API 会消失吗?

    Material 2 样式及其 API 将继续受到支持,并且我们没有立即计划弃用它们。我们知道应用程序切换到最新的 Material 3 样式需要一些时间,我们希望为迁移提供足够的时间。当我们决定删除这些 API 时,它们将被标记为已弃用,并在以下两个主要版本中继续受支持。截至目前,它们尚未被视为已弃用。

6. Angular 系列文章

最新更新以及更多 Angular 相关文章请访问 Angular 合集 | 鹏叔的技术博客

7. 参考文档

Material 3 Theming