Angular Material 的主题系统允许你为应用中的组件自定义基础、颜色、类型比例和密度样式。主题系统基于 Google 的 Material Design 规范。
本文档介绍了自定义颜色的概念和 API。关于排版的定制指南参见 Angular Material 排版。关于如何使用此系统来构建自定义组件的指南,请参阅 主题化你自己的组件。
Angular Material 的主题 API 是用 Sass 构建的。本文档假设你熟悉 CSS 和 Sass 的基础知识,包括变量、函数和 mixin。
你可以通过使用预构建的主题在没有 Sass 的情况下使用 Angular Material,如下面的使用预构建的主题所述。但是,直接使用库的 Sass API 能让你最大程度地控制应用程序中的样式。
调色板是代表颜色空间一部分的颜色集合。此集合中的每个值都称为色调。在 Material Design 中,调色板中的每个色调都有一个标识符数字。这些数字包括 50,以及 100 到 900 之间间隔 100 的所有值。这些编号会将调色板中的色调从最亮到最暗进行排序。
Angular Material 将调色板表示为 Sass 映射表。此映射表包含调色板的色调和每个色调的各个对比色的嵌套映射表。当使用某个色调作为背景色时,就会把其对比色用作文本颜色。下面的示例演示了调色板的结构。 更多背景信息,请参见 Material Design 的色彩体系。
$indigo-palette: (
50: #e8eaf6,
100: #c5cae9,
200: #9fa8da,
300: #7986cb,
// ... continues to 900
contrast: (
50: rgba(black, 0.87),
100: rgba(black, 0.87),
200: rgba(black, 0.87),
300: white,
// ... continues to 900
)
);
你可以通过定义与上面调色板部分中描述的结构相一致的 Sass 映射表来创建自己的调色板。映射表必须定义 50 的色调,以及 100 和 900 之间间隔 100 的每个色调。映射表还必须为每个色调定义具有对比色的 contrast
映射表。
你可以使用 Material Design 调色板工具来帮你选择调色板中的色调。
Angular Material 提供了基于 2014 版 Material Design 规范的预定义调色板。有关完整列表,请参阅 Material Design 2014 调色板。
除了编号从 0 到 900 的色调外,2014 年 Material Design 调色板还包括编号为 A100
、 A200
、 A400
和 A700
的显著强调色调。Angular Material 不需要这些色调,但你可以在定义主题时使用这些色调,如下面的定义主题中所述。
@use '@angular/material' as mat;
$my-palette: mat.$indigo-palette;
主题是颜色、类型比例和密度选项的集合。每个主题都包含三个调色板,用于确定组件颜色:
你可以通过两种方式在应用程序中包含主题的 CSS 样式:使用 Sass 自定义主题,或导入预构建的主题 CSS 文件。
主题文件是一个 Sass 文件,它会调用一些 Angular Material 的 Sass mixins 来输出颜色、排版和密集度这些 CSS 样式。
core
混合器Angular Material 定义了一个名为 core
的 mixin,其中包含供多个组件使用的通用功能的先决样式,例如涟漪。即使你定义了多个主题,core
mixin 也只能在应用程序中包含一次。如果多次包含 core
mixin,将导致应用程序中出现重复的 CSS。
@use '@angular/material' as mat;
@include mat.core();
Angular Material 将主题表示为一个 Sass 映射,其中包含你的颜色、类型比例和密度选择,以及一些基本设计系统设置。有关自定义类型比例的深入指南,请参阅 Angular Material 类型比例。有关调整组件密度的详细信息,请参阅下面的 自定义密度。
构建主题首先需要定义你的 primary
(主要)和 accent
(重音)调色板,以及可选的 warn
(警告)调色板。Sass 函数 define-palette
接受一个调色板(这在上面的调色板部分中讲过)以及四个可选的色调数值。这四种色调依次表示:“default(默认)”色调、“lighter(较浅)”色调、“darker(较暗)”色调和“text(文本)”色调。各个组件会使用这些色调为自身的不同部位选择最合适的颜色。
@use '@angular/material' as mat;
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
// The "warn" palette is optional and defaults to red if not specified.
$my-warn: mat.define-palette(mat.$red-palette);
你可以通过调用 define-light-theme
或 define-dark-theme
并以 define-palette
的结果为参数,来构建主题。选择使用浅色或深色主题,决定了整个组件使用的背景色和前景色。
@use '@angular/material' as mat;
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
// The "warn" palette is optional and defaults to red if not specified.
$my-warn: mat.define-palette(mat.$red-palette);
$my-theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
warn: $my-warn,
),
typography: mat.define-typography-config(),
density: 0,
));
Sass mixin core-theme
会为多个组件使用的通用功能(例如涟漪)生成先决样式。每个主题必须包含一次这个 mixin。
每个 Angular Material 组件都具有一个混合,用于每个
主题维度:基础、颜色、类型比例和密度。例如,
MatButton
声明
button-base
、
button-color
、
button-typography
和
button-density
。每个混合只发射与该自定义维度相对应的样式。
此外,每个组件都具有一个“主题”混合,它发射所有依赖于主题配置的样式。此主题混合仅在向
define-light-theme
或
define-dark-theme
提供了相应的配置时才发射颜色、类型比例或密度样式,并且它始终发射基础样式。
通过包含 (include
) 每个主题 Sass mixins,可以为应用程序中使用的每个组件应用样式。
@use '@angular/material' as mat;
@include mat.core();
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$my-theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
),
typography: mat.define-typography-config(),
density: 0,
));
// 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-light-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.
作为列出应用使用的所有组件的替代方法,Angular Material 提供了 Sass 混合,其中包含库中所有组件的样式:
all-component-bases
、
all-component-colors
、
all-component-typographies
、
all-component-densities
和
all-component-themes
。这些混合的行为与单个组件混合相同,只是它们为
core-theme
和 Angular Material 中的
所有 35 个以上组件发射样式。除非你的应用使用每个组件,否则这将生成不必要的 CSS。
@use '@angular/material' as mat;
@include mat.core();
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$my-theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
),
typography: mat.define-typography-config(),
density: 0,
));
@include mat.all-component-themes($my-theme);
要在你的应用程序中包含所生成的样式,请将你的主题文件添加到你项目的 angular.json
文件的 styles
数组中。
Angular Material 主题沿四个维度划分:基础、颜色、类型比例和密度。
设计系统通用的基础样式。这些样式不会根据你配置的颜色、排版或密集度而改变,因此每个应用只需要包含一次。这些混合包含结构样式,例如边框半径、边框宽度等。所有组件都有一个基础混合,可用于包含其基础样式。(例如,
@include mat.checkbox-base($theme)
)
与应用中的颜色相关的样式。这些样式应该在你的应用中至少包含一次。根据你的需求,你可能需要使用不同的配置多次包含这些样式。(例如,如果你的应用支持浅色和深色主题颜色。)所有组件都有一个颜色混合,可用于包含其颜色样式。(例如,
@include mat.checkbox-color($theme)
)
与应用中使用的字体相关的样式,包括字体系列、大小、粗细、行高和字母间距。这些样式应该在你的应用中至少包含一次。根据你的需求,你可能需要使用不同的配置多次包含这些样式。(例如,如果你的应用支持使用衬线或无衬线字体阅读内容。)所有组件都有一个排版混合,可用于包含其排版样式。(例如,
@include mat.checkbox-typography($theme)
)
与应用中元素的大小和间距相关的样式。这些样式应该在你的应用中至少包含一次。根据你的需求,你可能需要使用不同的配置多次包含这些样式。(例如,如果你的应用支持正常模式和紧凑模式。)所有组件都有一个密集度混合,可用于包含其密集度样式。(例如,
@include mat.checkbox-density($theme)
)
所有组件还支持一个主题混合,可用于一次性包含组件的所有主题维度样式。(例如,
@include mat.checkbox-theme($theme)
)。
推荐的方法是依赖
theme
混合来设置你的基础样式,如果需要,可以使用单维度混合来覆盖应用部分的特定方面(参见关于
在一个文件中使用多个主题 的部分)。
Angular Material 包括四个预构建的主题 CSS 文件,每个文件都选择了不同的调色板。如果你不想使用 Sass 来自定义主题,则可以使用这些预构建的主题之一。
主题 | 浅色还是深色? | 调色板(主色调、强调色、警告色) |
---|---|---|
deeppurple-amber.css |
浅色 | 深紫色、琥珀色、红色 |
indigo-pink.css |
浅色 | 靛蓝色、粉色、红色 |
pink-bluegrey.css |
深色 | 粉色、蓝灰色、红色 |
purple-green.css |
深色 | 紫色、绿色、红色 |
这些文件包括库中每个组件的 CSS。如果要单独包含这些组件的某个子集的 CSS,你必须使用上面定义主题中详述的 Sass API。你可以参考这些预建主题的源代码查看完整主题定义的示例。
你可以在 Angular Material 的 npm 包 ( @angular/material/prebuilt-themes
) 的 prebuilt-themes
目录中找到预构建的主题文件。要在你的应用程序中包含预先构建的主题,请将你选择的 CSS 文件添加到你项目的 angular.json
文件的 styles
数组中。
使用定义主题中描述的 Sass API,你还可以通过多次重复 API 调用来定义多重主题。你可以在同一个主题文件或几个单独的主题文件中执行此操作。
在单个文件中定义多重主题,能让你支持多重主题而无需管理多个 CSS 资产文件的加载。然而,代价是你的 CSS 将包含不必要的样式。
要控制何时应用哪个主题, 请在通过 CSS 规则声明指定的上下文中 @include
这些 mixin。有关更多背景信息,请参阅 Sass mixins 文档。
@use '@angular/material' as mat;
@include mat.core();
// Define a dark theme
$dark-theme: mat.define-dark-theme((
color: (
primary: mat.define-palette(mat.$pink-palette),
accent: mat.define-palette(mat.$blue-grey-palette),
),
// Only include `typography` and `density` in the default dark theme.
typography: mat.define-typography-config(),
density: 0,
));
// Define a light theme
$light-theme: mat.define-light-theme((
color: (
primary: mat.define-palette(mat.$indigo-palette),
accent: mat.define-palette(mat.$pink-palette),
),
));
// 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);
}
你可以创建多个主题文件,每个文件定义一个主题,然后将这些文件添加到 angular.json
的 styles
中,就可以在几个单独的文件中定义多重主题了。但是,你还必须将每个文件的 inject
选项设置为 false
,以防止同时加载所有主题文件。当此属性为 false
时,你的应用程序要负责手动加载所需的文件。加载的方式则取决于你的应用程序。
默认情况下,Angular Material 不会将任何样式应用到你的 DOM 组件外部。如果想设置应用程序的背景颜色以匹配组件的主题,你可以:
MatSidenav
,将你的应用的主要内容放在
mat-sidenav-container
中,或者mat-app-background
CSS 类应用到你主要内容的根元素(通常是 body
)。你可以使用 Angular Material 的各个 Sass mixin 来自定义应用程序中特定范围内的组件样式。包含(include) Sass mixin 的 CSS 规则声明决定了它的作用域。下面的示例展示了如何自定义带有 .my-special-section
CSS 类的元素内所有按钮的颜色。
@use '@angular/material' as mat;
.my-special-section {
$special-primary: mat.define-palette(mat.$orange-palette);
$special-accent: mat.define-palette(mat.$brown-palette);
$special-theme: mat.define-dark-theme((
color: (primary: $special-primary, accent: $special-accent),
));
@include mat.button-color($special-theme);
}
可以从主题中读取颜色,并在你自己的组件中使用。有关此方面的更多信息,请参阅我们关于 主题化你自己的组件 的指南。
Angular Material 的密集度自定义基于 Material Design 密集度指南。此系统定义了一个比例尺,其中零表示默认密集度。你可以减小数字以获得 更高密集度,增加数字以获得 更低密集度。
密集度系统基于
密集度比例尺。比例尺从默认密集度
0
开始。每个向下整数值步骤(
-1
、
-2
等)将受影响的大小减少
4px
,直到组件渲染所需的最小尺寸。
出现在基于任务或弹出式上下文中的组件,例如
MatDatepicker
,不会通过密集度系统改变其大小。
Material Design 密集度指南 明确反对在这些交互中增加密集度,因为它们不会与应用布局中的空间竞争。
你可以使用它们的密集度 Sass 混合,将自定义密集度设置应用于整个库或单个组件。
// You can set a density setting in your theme to apply to all components.
$dark-theme: mat.define-dark-theme((
color: ...,
typography: ...,
density: -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);
}
默认情况下,大多数组件通过更改 Material Design 规范中描述的背景颜色来指示浏览器焦点。但是,此行为可能无法满足无障碍性要求,例如 WCAG,后者要求更强烈地指示浏览器焦点。
Angular Material 支持在有焦点的元素上渲染高度可见的轮廓。应用程序可以通过两个 Sass mixin 启用这些强烈焦点指示器: strong-focus-indicators
和 strong-focus-indicators-theme
。
strong-focus-indicators
mixin 会为所有组件生成结构化指示器样式。这个 mixin 应该在应用程序中只包含一次,类似于上面描述的 core
mixin。
strong-focus-indicators-theme
mixin 只会生成指示器的颜色样式。这个 mixin 应该包含在每个主题中,类似于上面描述的主题 mixin。此外,在默认颜色与背景颜色对比不足的情况下,你可以使用此 mixin 来更改焦点指示器的颜色。
以下示例在应用程序中包含强烈焦点指示器样式以及自定义主题 API 的其余部分。
@use '@angular/material' as mat;
@include mat.core();
@include mat.strong-focus-indicators();
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$my-theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
)
));
@include mat.all-component-themes($my-theme);
@include mat.strong-focus-indicators-theme($my-theme);
你可以将配置映射传递给 strong-focus-indicators
以自定义指标的外观。此配置包括 border-style
、 border-width
和 border-radius
。
你还可以使用 strong-focus-indicators-theme
自定义指标的颜色。这个 mixin 接受一个主题,如本指南前面所述,或者一个 CSS 颜色值。提供主题时,指标将使用主调色板的默认色调。
以下示例包括具有自定义设置的强烈焦点指示器样式以及自定义主题 API 的其余部分。
@use '@angular/material' as mat;
@include mat.core();
@include mat.strong-focus-indicators((
border-style: dotted,
border-width: 4px,
border-radius: 2px,
));
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$my-theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
)
));
@include mat.all-component-themes($my-theme);
@include mat.strong-focus-indicators-theme(purple);
Angular Material 假定,默认情况下,所有主题样式都作为全局 CSS 加载。如果要在应用程序中使用 Shadow DOM,则必须在每个包含 Angular Material 组件的 Shadow Root 中加载主题样式。你可以通过在每个 Shadow Root 中手动加载 CSS 或使用可构造样式表 来完成此操作。
Angular Material 不会根据用户偏好媒体查询(例如
prefers-color-scheme
或
prefers-contrast
)应用样式。相反,Angular Material 的 Sass 混合提供了灵活性,可以根据对你用户最有意义的条件来应用主题样式。这可能意味着直接使用媒体查询或读取保存的用户偏好。
Angular Material 支持自定义颜色、排版和密集度,如本文档所述。Angular 强烈反对,并且不直接支持在上述主题 API 之外覆盖组件 CSS。组件 DOM 结构和 CSS 类被视为私有实现细节,可能会随时更改。