Angular Material 18+ 高级教程 – Custom Themes for Material Design 3 (自定义主题 Material 3)
v18 更新重要说明
从 Angular Material v18 开始,默认使用的是 Material 3 Design (简称 M3)。
而且是正式版,不再是 experimental preview 了。
由于本篇写的时候是 v17,而我现在没力修改下面的 demo 代码,所以这里 highlight 一下 breaking changes 就好:
不需要 @angular/material-experimental
@use '@angular/material-experimental' as matx;
直接用 @angular/material 即可
@use '@angular/material' as mat;
不需要 m3 prefix 了,比如
matx.$m3-blue-palette
换成
mat.$blue-palette如果是用 m2 版本,反而要加上 prefix m2
mat.define-dark-theme
换成
mat.m2-define-dark-theme
前言
续上一篇的 Custom Themes for Material Design 2 (简称 M2) 之后,我们继续看 Material Design 3 (简称 M3)。(提醒:没有看过 M2 的朋友请先看 M2 的哦)
Angular Material v17.2.0 发布了对 Material Design 3 的实现 (preview 版本)。
M2 和 M3 主要只是样式不同而已,组件的交互,使用接口等等全部都一样,所以你也可以把它理解为只是换了一个默认主题 (Theme)。
参考
Angular Material Docs – Material 3 Theming
Material Design Docs – Color System
Material Design Docs – Typography
Angular Material Design 3 Get Started
首先添加 Angular Material
ng add @angular/material
选择 Custom Theme

添加 @angular/material-experimental 包
yarn add @angular/material-experimental
App Template
<mat-card>
<mat-card-header>
<mat-card-title>Title</mat-card-title>
<mat-card-subtitle>Subtitle</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium, iusto?</p>
<div class="button-list">
<button mat-raised-button color="primary">Primary</button>
<button mat-raised-button color="accent">Accent</button>
<button mat-raised-button color="warn">Warn</button>
</div>
</mat-card-content>
</mat-card>
App Styles (美化一下而已)

mat-card {
max-width: 360px;
mat-card-content {
padding: 16px;
.button-list {
margin-top: 16px;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
}
}
styles.scss (先来个 M2 版本)

@use '@angular/material' as mat; @include mat.core(); $m2-primary: mat.define-palette(mat.$indigo-palette);
$m2-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$m2-warn: mat.define-palette(mat.$red-palette); $m2-typography: mat.define-typography-config();
$m2-theme: mat.define-light-theme((
color: (
primary: $m2-primary,
accent: $m2-accent,
warn: $m2-warn,
),
typography: $m2-typography
));
@include mat.all-component-themes($m2-theme);
效果

styles.scss (M3 版本)
@use '@angular/material' as mat;
@use '@angular/material-experimental' as matx; @include mat.core(); $m3-theme: matx.define-theme((
color: (
theme-type: light,
primary: matx.$m3-blue-palette,
tertiary: matx.$m3-red-palette,
),
typography: (
plain-family: 'Roboto',
brand-family: 'Roboto',
bold-weight: 700,
medium-weight: 500,
regular-weight: 400
),
density: (
scale: 0
)
)); html {
@include mat.all-component-themes($m3-theme);
}
效果

M2 和 M3 的风格差别挺大的,圆角更明显了,颜色运用不太一样,字体尺寸也有微调。
不过这些我都不关心,毕竟我不是设计师,看不出哪一个比较好。
对比 Material 2 和 Material 3
首先是 M3 需要引入多一个包 @angular/material-experimental
@use '@angular/material' as mat;
@use '@angular/material-experimental' as matx;
当然,它依然需要 @angular/material 包,因为 M3 并不是一个全新的 Material Design 实现,它只是一个新主题而已。
Define Color Theme
$m3-color-theme: matx.define-theme((
color: (
theme-type: light,
primary: matx.$m3-blue-palette,
tertiary: matx.$m3-green-palette,
)
));
M3 和 M2 有几个区别:
M2 有 define-light-theme 和 define-dark-theme 两个方法。
而 M3 只有一个 define-theme 方法,取而代之的是它的 color 参数有一个 theme-type 属性用来表达是 light theme or dark theme。
M2 可以配置 primary, accent, warn 三个颜色
M3 只可以配置 primary 和 tertiary 两个颜色
这个 tertiary 相等于 M2 的 accent,而 M2 的 warn 在 M3 叫 error。
M3 目前不支持 Custom Base Palette (M2 支持),我们只能选择几个固定的颜色

Define Typography Theme
$m3-typography-theme: matx.define-theme((
typography: (
brand-family: 'Roboto',
plain-family: 'Roboto',
bold-weight: 700,
medium-weight: 500,
regular-weight: 400
),
));
M3 和 M2 有几个区别:
M3 不允许调整 Type Scale Level
M3 只允许调整 5 个属性
brand-family 用于 headline
plain-family 用于 paragraph
regular, medium, bold 用于 font-weight
M3 的 Type Scale Level 有新的命名和尺寸
它分 5 个大 Level:Display,Headline,Title,Body,Label
大 Level 里又分小 Level:Large,Medium,Small

Define Density Theme
$m3-density-theme: matx.define-theme((
density: (
scale: 0
)
));
scale 最大是 0,最小是 -3
Apply Theme to Components
M3 apply theme 的方式和 M2 大同小异。
html {
@include mat.all-component-bases($m3-theme);
}
唯一的区别是 M3 一定要 under 某个 selector。通常放 html {} 或者 :root 都可以。
mat.all-component-bases 输出的是 CSS Variables,这点 M2 和 M3 都是一样的。
apply theme 1 by 1:
html {
@include mat.all-component-bases($m3-base-theme);
@include mat.all-component-colors($m3-color-theme);
@include mat.all-component-typographies($m3-typography-theme);
@include mat.all-component-densities($m3-density-theme);
}
apply components 1 by 1:
html {
@include mat.button-base($m3-base-theme);
@include mat.button-color($m3-color-theme);
@include mat.button-typography($m3-typography-theme);
@include mat.button-density($m3-density-theme);
}
Color Variants
眼尖的朋友或许会发现到 color 属性失灵了
<button mat-raised-button color="primary">Primary</button>
<button mat-raised-button color="accent">Accent</button>
<button mat-raised-button color="warn">Warn</button>

三个 Button 的颜色都是 primary。
<button mat-raised-button color="tertiary">Accent</button>
<button mat-raised-button color="error">Error</button>
即便换成最新的命名效果也是一样。
这是因为,M3 不再自动输出相关代码。
我们看看 M2
@include mat.button-color($m2-theme);
M2 会自动输出下面这几段

M3 则不会了。
解决方法有 2 个:
自己补上
html {
.mat-mdc-raised-button.mat-tertiary {
@include mat.button-color($m3-color-theme, $color-variant: tertiary);
}
.mat-mdc-raised-button.mat-error {
@include mat.button-color($m3-color-theme, $color-variant: error);
}
}<button color="tertiary"> Angular Material 会自动添加 class mat-tertiary
使用向后兼容方法
html {
@include matx.color-variants-back-compat($theme);
}color-variants-back-compat 是 Angular Material 特别为了方便向后兼容而设的。
它的源码在 _color-api-back-compat.scss

最终也是使用了 @include mat.button-color($m3-color-theme, $color-variant: tertiary)

Custom component reads theme information
M2 和 M3 大同小异,方法是同一个,只是参数有些换了而已。
Reads color theme information
依然是使用 mat.get-theme-color 方法,但是参数不一样。
它有两种调用方式:
Reading tonal palette colors
第一种调用方式是传入 3 个参数,这个叫 Reading tonal palette colors。
参数一是 $m3-theme
参数二是 Palette Name,选项有:
- primary
- secondary
- tertiary
- error
- neutral
- neutral-variant
参数三是明度 Level,选项有:
- 0
- 10
- 20
- 30
- 40
- 50
- 60
- 70
- 80
- 90
- 95
- 99
- 100

Reading color roles
第二种调用方式是传入 2 个参数,这个叫 Reading color roles。
参数一是 $m3-theme
参数二是 Role Name:
primaryon-primaryprimary-containeron-primary-containerprimary-fixedprimary-fixed-dimon-primary-fixedon-primary-fixed-variantsecondaryon-secondarysecondary-containeron-secondary-containersecondary-fixedsecondary-fixed-dimon-secondary-fixedon-secondary-fixed-varianttertiaryon-tertiarytertiary-containeron-tertiary-containertertiary-fixedtertiary-fixed-dimon-tertiary-fixedon-tertiary-fixed-varianterroron-errorerror-containeron-error-containersurface-dimsurfacesurface-brightsurface-container-lowestsurface-container-lowsurface-containersurface-container-highsurface-container-higheston-surfaceon-surface-variantoutlineoutline-variantinverse-surfaceinverse-on-surfaceinverse-primaryscrimshadow
想多了解 Color Roles 可以看这篇 Docs – Color roles。
举个例子,我们设定的 primary color 被用于 Container (通常指 background-color) 时,它的颜色并不是 primary 而是会浅一点。

On Primary Container 的 On 指的是 On Top,也就是 bg-color 和 color 的 contrast 关系。
M3 的颜色用法和 M2 不太一样,M2 我们会拿 primary default,primary lighter,而 M3 我们不太会拿 primary 50,取而代之的是直接拿 primary-container。
另外,M2 可以拿组件 (e.g. dialog, button) 的 foreground 和 background,M3 则不行。
Apply alpha to color
mat.get-theme-color 方法返回的是 HEX (hexadecimal),如果想加入 alpha 可以利用 alpha hexadecimal (#RRGGBBAA)。
background-color: #{mat.get-theme-color($m3-color-theme, primary)} + '09';
--background-color: #{mat.get-theme-color($m3-color-theme, primary)}09;
如果想更灵活可以把 hex 转换成 hsl (提醒:转换后颜色可能会有微差哦)
$color: mat.get-theme-color($m3-color-theme, primary);
$hue: color.hue($color);
$saturation: color.saturation($color);
$lightness: color.lightness($color); app-root {
--primary-hsl-value: #{$hue} #{$saturation} #{$lightness};
background-color: hsl(var(--primary-hsl-value) / 50%);
}
Reads typography theme information
和 M2 一样使用 mat.get-theme-typography 方法,参数也一样,只是 Scale Level Name 换了。
M3 Scale Level Name:
display-largedisplay-mediumdisplay-smallheadline-largeheadline-mediumheadline-smalltitle-largetitle-mediumtitle-smallbody-largebody-mediumbody-smalllabel-largelabel-mediumlabel-small
Reads density theme information
和 M2 一摸一样,这里就不复述了。
总结
1. M3 是建立在 M2 基础上的,所以必须先掌握 M2
2. M3 主要是改了 Styles (CSS) 的部分,组件交互 (TS) 的部分完全没有变动。
2. M3 的颜色运用和 M2 区别比较大,这个是 Material Design 的知识,多参考 Material Design 3 Color System
3. M3 的 Typography 不能自定义 Type Scale Level 尺寸了,而且 Type Scale Level Name 都换了。
4. M3 目前是 preview 版本,不过相信 Angular Material v18 就会变成稳定版了,因为它也不算是大改。
M3 给我的感觉是限制更多了,能自定义的地方更少了。
目录
上一篇 Angular Material 18+ 高级教程 – Custom Themes for Material Design 2 (自定义主题 Material 2)
下一篇 Angular Material 18+ 高级教程 – CDK Portal
想查看目录,请移步 Angular 18+ 高级教程 – 目录
喜欢请点推荐,若发现教程内容以新版脱节请评论通知我。happy coding
Angular Material 18+ 高级教程 – Custom Themes for Material Design 3 (自定义主题 Material 3)的更多相关文章
- Siki_Unity_2-9_C#高级教程(未完)
Unity 2-9 C#高级教程 任务1:字符串和正则表达式任务1-1&1-2:字符串类string System.String类(string为别名) 注:string创建的字符串是不可变的 ...
- Pandas之:Pandas高级教程以铁达尼号真实数据为例
Pandas之:Pandas高级教程以铁达尼号真实数据为例 目录 简介 读写文件 DF的选择 选择列数据 选择行数据 同时选择行和列 使用plots作图 使用现有的列创建新的列 进行统计 DF重组 简 ...
- ios cocopods 安装使用及高级教程
CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...
- 【读书笔记】.Net并行编程高级教程(二)-- 任务并行
前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术.现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题. 1 ...
- 【读书笔记】.Net并行编程高级教程--Parallel
一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控>这本书中也多次提到并发,不管是计算机 ...
- 分享25个新鲜出炉的 Photoshop 高级教程
网络上众多优秀的 Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享25个新鲜出炉的 Photoshop 高级教程,提高你的设计技巧,制作时尚的图片效果.这 ...
- 展讯NAND Flash高级教程【转】
转自:http://wenku.baidu.com/view/d236e6727fd5360cba1adb9e.html 展讯NAND Flash高级教程
- Net并行编程高级教程--Parallel
Net并行编程高级教程--Parallel 一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控 ...
- [转帖]tar高级教程:增量备份、定时备份、网络备份
tar高级教程:增量备份.定时备份.网络备份 作者: lesca 分类: Tutorials, Ubuntu 发布时间: 2012-03-01 11:42 ė浏览 27,065 次 61条评论 一.概 ...
- Django 2.0.1 官方文档翻译: 高级教程:如何编写可重用的app (page 13)
高级教程:如何编写可重用的app (page 13) 本节教程上接第七部分(Page 12).我们会把我们的 web-poll应用转换成一个独立的python包,你可以在新的项目中重用或者把它分享给其 ...
随机推荐
- 做独立开发者,能在 AppStore 赚到多少钱?
成为一名独立开发者,不用朝九晚五的上班,开发自己感兴趣的产品,在AppStore里赚美金,这可能是很多程序员的梦想,今天就来盘一盘,这个梦想实现的概率有多少. (Solo社区 投稿) 先来了解一些数据 ...
- VPS测试脚本,网络线路,路由测试,流媒体服务器测试脚本
收集了一些服务器测试脚本,测试性能,网络以及解锁Netflix等服务.记录收集一下,特此记录. yabs测试脚本wget -qO- yabs.sh | bash 老外比较爱用的服务器性能测试脚本. ...
- 实用!一键生成数据库文档的神器,支持MySQL/SqlServer/Oracle多种数据库
Screw(螺丝钉)是一款简洁好用的数据库表结构文档生成工具,它的特点是:简洁.轻量.设计良好.多数据库支持.多种格式文档.灵活扩展以及支持自定义模板,对于有经常要进行数据库设计.评审.文档整理等需求 ...
- 工作单元(UnitOfWork) 模式 (2) .NET Core
1.工作单元(UnitOfWork)是什么? Maintains a list of objects affected by a business transaction and coordinate ...
- 寒假训练——vj题解
B - B M 算日期 M 是一位数学高手,今天他迎来了 Kita 的挑战.Kita 想让 BM 算出这几年内有多少个闰年. BM 觉得这问题实在太简单了,于是 Kita 加大了难度. 他先给出第一个 ...
- php 模型浏览器
docker安装 文档:https://github.com/SeleniumHQ/docker-selenium docker run -d -p 4444:4444 -p 7900:7900 -- ...
- mybatis关于大于小于:元素内容必须由格式正确的字符数据或标记组成。
首先是原因: mybatis中< >这两个符号会被识别为标签的开始和结束,用了就会报解析的错误 会报错类似下面这些 1.元素内容必须由格式正确的字符数据或标记组成. 2.Error cre ...
- MSPM0G3507外设DMA学习笔记
概述 变量的存储 正常情况下,变量存储在SRAM中,如果要发送该变量的值到外设,需要调用内核操作,使SRAM中的数据送到外设. 此类型操作过多会导致占用CPU高,整体卡顿. DMA控制概述 DMA:D ...
- ComfyUI插件:ComfyUI Impact 节点(二)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器.细节强化器.预览桥.通配符.Hook.图片发送器.图片 ...
- 自写Json转换工具
前面写了简单的API测试工具ApiTools,返回的json有时需要做很多转换,于是开发了这个工具. 功能包括 1.json字符串转为表格,可以直观的展示,也可以复制,并支持转换后的表格点击列头进行排 ...