Angular Material MatButton 完全指南:变体、外观、图标定位与无障碍实践
2026/9/12 12:20:57 网站建设 项目流程

Angular Material MatButton 完全指南:变体、外观、图标定位与无障碍实践

【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components

Angular Material 的按钮组件(MatButton)以原生<button><a>元素为基础,叠加 Material Design 视觉样式与无障碍能力,是组件库中使用频率最高的交互控件之一。本文基于本仓库中 button.md 的官方文档,结合 按钮源码实现 与 官方示例,系统讲解按钮的四种变体、五种外观(appearance)、图标投影规则、交互式禁用、进度指示器及无障碍最佳实践,帮助你写出语义正确、可访问、可复用的 Angular Material 按钮。

按钮的本质:增强原生元素,而非替换

Angular Material 按钮始终使用原生<button><a>元素,仅通过指令(directive)叠加 Material Design 样式。之所以坚持这一设计,是为了给用户提供最直接、最无障碍的使用体验,具体遵循以下选择原则:

  • 执行动作(如保存、提交、删除)时,使用<button>元素;
  • 跳转导航(如跳转到另一个视图或 URL)时,使用<a>元素。

这一点在组件声明中体现得很直接:MatButton的选择器同时覆盖了按钮与锚点两种形态,见 button.ts:

selector: ` button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] `,

值得注意的是,组件还保留了mat-buttonmat-raised-buttonmat-flat-buttonmat-stroked-button等旧版选择器以向后兼容。在构造函数中,组件会通过_inferAppearance从这些静态属性推断外观(见 button.ts):mat-raised-button推断为elevatedmat-stroked-button推断为outlinedmat-flat-button推断为filledmat-button推断为text。这意味着旧项目迁移到新版后,原有标记无需改动即可获得正确外观。

四种按钮变体(Variants)

Angular Material 提供四种按钮变体,每种都以属性(attribute)形式应用在元素上:

属性说明
matButton矩形按钮,可包含文本与图标,是最通用的按钮形态
matIconButton更小的圆形按钮,用于容纳单个图标,不包含文本
matFab悬浮操作按钮(Floating Action Button),带高度与圆角,用于容纳图标;可通过extended属性扩展为矩形以容纳文字标签
matMiniFabmatFab的缩小版

从源码看,各变体有独立的组件类与样式文件:MatFabButtonMatMiniFabButton定义于 fab.ts,MatIconButton定义于 icon-button.ts,并统一由 MatButtonModule 导出。FAB 类组件在宿主元素上设置了mdc-fab相关类,并通过_isFab = true标记让涟漪(ripple)使用 FAB 专属样式。

快速上手示例

以下模板来自官方示例 button-overview-example.html,展示了三种基础形态:

<button matButton>Basic</button> <button matButton disabled>Disabled</button> <a matButton href="https://www.google.com/" target="_blank">Link</a> <button matFab aria-label="Example icon button with a delete icon"> <mat-icon>delete</mat-icon> </button> <button matMiniFab aria-label="Example icon button with a menu icon"> <mat-icon>menu</mat-icon> </button>

五种外观(Appearance)

matButton支持通过属性值设置多种外观,例如matButton="outlined"。下表列出了全部外观及其适用场景:

外观说明
text默认外观。文本按钮用于最低优先级的操作,尤其是在需要呈现多个选项时
filled高强调按钮,用于流程中的最终或解锁性操作,例如保存、确认
tonal中强调按钮,常用于流程中的最终或解锁性操作,但视觉强调度低于filled
outlined中强调按钮,常用于需要引起注意但并非主操作的动作
elevated中强调按钮,常用于按钮需要与有图案的背景产生视觉分隔的场景

外观到 CSS 类的映射维护在APPEARANCE_CLASSES中(见 button.ts):

const APPEARANCE_CLASSES: Map<MatButtonAppearance, readonly string[]> = new Map([ ['text', ['mat-mdc-button']], ['filled', ['mdc-button--unelevated', 'mat-mdc-unelevated-button']], ['elevated', ['mdc-button--raised', 'mat-mdc-raised-button']], ['outlined', ['mdc-button--outlined', 'mat-mdc-outlined-button']], ['tonal', ['mat-tonal-button']], ]);

设置外观时,组件会先移除旧外观对应的类,再添加新外观的类(见 setAppearance)。同时,appearance输入允许空字符串,这样matButton单独使用时无需写出="text",默认回落到text

五种外观的完整模板

<button matButton>Basic text button</button> <button matButton="elevated">Elevated button</button> <button matButton="outlined">Outlined button</button> <button matButton="filled">Filled button</button> <button matButton="tonal">Tonal button</button>

扩展 FAB 按钮(Extended FAB)

传统悬浮操作按钮(FAB)是圆形的,只能容纳一个图标。添加extended属性后,FAB 会扩展为带圆角的矩形,在图标之外还能容纳文字标签:

<button matFab extended> <mat-icon>home</mat-icon> Home </button>

需要注意的是,只有全尺寸 FAB 支持extended属性,mini FAB 不支持。源码中extended是一个布尔转换输入(见 fab.ts),并通过宿主绑定添加mdc-fab--extendedmat-mdc-extended-fab类:

@Input({transform: booleanAttribute}) extended: boolean = false; host: { '[class.mdc-fab--extended]': 'extended', '[class.mat-mdc-extended-fab]': 'extended', }

扩展 FAB 同样支持链接形态,可配合routerLink使用:

<a matFab extended routerLink="."> <mat-icon>favorite</mat-icon> Link </a>

图标定位(Icon Positioning)

按钮可以在文本旁容纳图标。默认情况下,图标(mat-icon.material-icons,或带matButtonIcon属性的元素)会被投影到按钮标签之前

<button matButton> <mat-icon>favorite</mat-icon> Like </button>

要把图标放到标签之后,只需在图标元素上加iconPositionEnd属性:

<button matButton> Send <mat-icon iconPositionEnd>send</mat-icon> </button>

也可以同时使用两个位置:

<button matButton> <mat-icon>arrow_back</mat-icon> Navigate <mat-icon iconPositionEnd>arrow_forward</mat-icon> </button>

如果你使用的是自定义图标元素(既不是mat-icon也不是.material-icons),需要添加matButtonIcon属性,按钮才能将其投影到正确的插槽:

<button matButton> <my-custom-icon matButtonIcon>custom</my-custom-icon> Action </button>

这一行为在模板 button.html 中通过三段<ng-content>实现:前段投影不含iconPositionEnd的图标,中段是标签容器mdc-button__label,后段投影带iconPositionEnd的图标。模板还支持 Material Symbols(.material-symbols-outlined.material-symbols-rounded.material-symbols-sharp)系列的图标类。

交互式禁用按钮(Interactive Disabled Buttons)

原生禁用的<button>元素无法获得焦点,也不会派发任何事件。这在某些场景下会带来问题——例如应用无法告知用户按钮为何被禁用。disabledInteractive输入可以将按钮样式化为禁用状态,同时仍允许其获得焦点并派发事件,并会为辅助技术设置aria-disabled="true"

<button matButton="elevated" disabled disabledInteractive matTooltip="This is a tooltip!"> Disabled button allowing interactivity </button>

上面的示例来自 button-disabled-interactive-example.html,它借助 tooltip 向用户解释禁用原因——这正是原生禁用按钮无法做到的。对比之下,普通disabled按钮无法触发 tooltip。

重要警示:使用disabledInteractive可能导致原本会被阻止的操作不再被阻止,例如表单中的提交按钮。启用该输入时,应在组件中自行防护这类情况。

从源码看(见 button-base.ts),该行为通过多个宿主属性协同实现:

  • _getDisabledAttribute():仅在disabledInteractive || !disabled时为null,否则返回true,即交互式禁用不会写入原生disabled属性;
  • _getAriaDisabled():对按钮元素,仅当disabled && disabledInteractive时返回true,从而为辅助技术标记禁用;
  • _getTabIndex():锚点元素在disabled && !disabledInteractive时返回-1,交互式禁用时保持可聚焦。

同时,button-base.ts 中为锚点注册了点击拦截:当锚点被禁用时,阻止默认行为并停止事件冒泡。

全局配置 MAT_BUTTON_CONFIG

交互式禁用行为可以通过MAT_BUTTON_CONFIG注入令牌全局配置。该令牌在 button-base.ts 中定义:

export interface MatButtonConfig { /** Whether disabled buttons should be interactive. */ disabledInteractive?: boolean; /** Default palette color to apply to buttons. */ color?: ThemePalette; /** Default appearance for plain buttons (not icon buttons or FABs). */ defaultAppearance?: MatButtonAppearance; }

在应用启动时全局提供:

import {MAT_BUTTON_CONFIG} from '@angular/material/button'; providers: [ { provide: MAT_BUTTON_CONFIG, useValue: { disabledInteractive: true, defaultAppearance: 'tonal', }, }, ]

构造函数会读取该配置并作为默认值(见 button-base.ts),单个按钮上的显式输入始终可以覆盖全局默认。此外,MatButtonappearancesetter 也会回退到this._config?.defaultAppearance(见 button.ts),因此defaultAppearance可用于统一全站按钮外观。

带进度指示器的按钮(Buttons with Progress Indicators)

按钮可以投影一个带progressIndicator属性的元素。当showProgress输入为true时,该元素会覆盖显示在按钮内容之上,同时按钮原有内容变为不可见。

<button matButton="outlined" [showProgress]="showProgress()" (click)="toggleShowProgress()"> Click to toggle progress <mat-progress-spinner progressIndicator mode="indeterminate" diameter="20" aria-label="Loading" tabindex="" /> </button>

上面的代码来自官方示例 button-progress-indicator-example.html。同一示例还展示了自定义进度指示器的写法——不依赖MatProgressSpinner,用带role="progressbar"的普通元素即可:

<button matButton="outlined" [showProgress]="showProgress()" (click)="toggleShowProgress()"> Click to toggle progress <div progressIndicator role="progressbar" aria-valuemin="0" aria-valuemax="100"> Loading... </div> </button>

模板实现上(见 button.html),当showProgress()为真时渲染mat-mdc-button-progress-indicator-container容器并投影[progressIndicator]元素;宿主上同时添加mat-mdc-button-progress-indicator-shown类(见 button-base.ts)来驱动内容隐藏样式。

无障碍要求

投影的进度指示器元素不得可交互。使用MatProgressSpinner作为指示器时,应设置tabindex="",将其从 Tab 键顺序中移除(如上例所示)。

无障碍(Accessibility)

Angular Material 默认使用原生<button><a>元素来保证无障碍体验:

  • 在当前页面执行动作的交互,使用<button>
  • 导航到另一个 URL的交互,使用<a>

MatButton同样适用按钮与锚点的所有标准无障碍最佳实践。

大写文本(Capitalization)

按钮文本本身使用全大写会导致屏幕阅读器逐字符朗读,也会引发本地化问题。因此官方不建议修改按钮文本的默认大小写

禁用锚点(Disabling anchors)

MatAnchor在原生<a>元素能力之外还支持禁用锚点。禁用时,组件会设置aria-disabled="true"tabindex="-1",并在点击时拦截默认跳转(见 button-base.ts)。由于禁用锚点的辅助技术支持情况可能因读屏软件而异,官方建议始终在应用中测试禁用锚点的行为

纯图标按钮(Buttons with icons)

仅包含图标的按钮或链接(如matFabmatMiniFabmatIconButton)应通过aria-labelaria-labelledby提供有意义的标签,例如官方示例中的aria-label="Example icon button with a delete icon"。此外,为保证充分可访问,图标的最小触控目标应为 48x48 像素,尤其在移动设备与小屏上要确保易于点击——模板末尾的mat-mdc-button-touch-target元素(见 button.html)正是用于扩展触控区域。

切换按钮(Toggle buttons)

需要带状态的切换按钮(toggle button)时,请参阅MatButtonToggle组件的文档(仓库内对应实现位于 src/material/button-toggle),MatButton本身不提供状态保持能力。

小结与延伸阅读

总结本指南的关键要点:

  1. 语义优先:动作用<button>,导航用<a>,组件只增强样式与交互,不替换原生语义;
  2. 四种变体matButtonmatIconButtonmatFabmatMiniFab,按内容形态选用;
  3. 五种外观textfilledtonaloutlinedelevated,按强调等级与场景选用,旧版mat-*-button属性可自动推断外观;
  4. 图标灵活布局:默认前置,iconPositionEnd后置,自定义图标用matButtonIcon标记;
  5. 禁用态精细化disabledInteractive配合MAT_BUTTON_CONFIG实现可聚焦、可解释的禁用态;
  6. 进度反馈progressIndicator+showProgress让按钮承载加载状态;
  7. 无障碍是默认项:遵循大写、禁用锚点、图标标签、48px 触控目标等实践。

如需进一步深入,可以阅读本仓库中的相关源码与测试:按钮核心实现见 button.ts、button-base.ts、fab.ts 与 icon-button.ts,样式体系见 _m3-button.scss、_m2-button.scss 与 _button-theme.scss,完整行为测试见 button.spec.ts,可直接运行的示例见 button-overview。

【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询