はじめに
Angularでアプリを作り始めると、必ずぶつかるのがボタン・ダイアログ・日付選択・テーブルといった「よくあるUI部品」をどう用意するかという問題です。CSSフレームワークだけを入れても、Angularのフォームやアクセシビリティ属性、フォーカス管理まで自前で組み込むのは意外と骨が折れます。かといって毎回自作していては、プロジェクトが増えるたびに同じコンポーネントを作り直すことになりかねません。
Angular Materialは、この「UI部品を自分で作り込む」作業をまるごと肩代わりしてくれる、Angularチーム自身が開発・保守する公式ライブラリです。Material Designに準拠したコンポーネント一式に加えて、アクセシビリティやキーボード操作、フォーカストラップまで最初から実装済みの状態で提供されるため、見た目だけでなく品質の底上げにもつながります。この記事では、Angular Materialの特徴からインストール、実践的な使い方までを解説します。
Angular Materialとは
Angular Materialは、GoogleのAngularチームが開発する公式UIコンポーネントライブラリです。npmパッケージ名は@angular/materialで、bestofjsなどでは「Material Design for Angular」という名称でも紹介されています。ボタンやフォーム部品、ダイアログ、テーブルといった30種類以上のコンポーネントを、Material Designの仕様に沿った形で提供します。
GitHubリポジトリangular/componentsは25,000以上のスターを獲得しており、Angular本体と歩調を合わせてリリースが続く、Angularエコシステムの中核ライブラリのひとつです。
主な特徴
- 公式メンテナンスによる高い信頼性 - Angular本体と同じチームが開発しているため、Angularの新機能(Standaloneコンポーネント、Signalsなど)への追従が早い
- Angular CDK同梱 -
@angular/cdkがベースにあり、オーバーレイ・ドラッグ&ドロップ・仮想スクロール・アクセシビリティなど、見た目を持たない「振る舞い」だけを取り出して使うこともできる - Material 3(M3)テーマ対応 -
mat.define-themeによるトークンベースのテーマシステムがv18で安定版になり、配色・形状・密度を細かくカスタマイズできる - アクセシビリティが標準搭載 - ARIA属性、キーボードナビゲーション、フォーカス管理がコンポーネントに組み込み済み
- Standaloneコンポーネントとして提供 - 各コンポーネントを
MatButtonのように個別importでき、NgModuleを使わない構成にも対応
インストール
Angular MaterialはAngular CLIのng addでインストールするのが公式に推奨されている方法です。CDK・Animationsも合わせて導入され、テーマの選択やグローバルスタイルの設定まで対話形式で進みます。
ng add @angular/material
npm経由で個別にインストールすることも可能です。
npm install @angular/material @angular/cdk @angular/animations
執筆時点の最新バージョンは22.1.1で、対応するAngular本体のメジャーバージョンと揃えて使うのが基本です。
基本的な使い方
Angular Materialのコンポーネントは、使う分だけを個別にimportして使うStandalone構成が基本です。ボタンとカードを組み合わせた最小構成は次のようになります。
import { Component } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'app-hello',
standalone: true,
imports: [MatButtonModule, MatCardModule],
template: `
<mat-card>
<mat-card-header>
<mat-card-title>ようこそ</mat-card-title>
</mat-card-header>
<mat-card-content>
<p>Angular Materialのカードとボタンです。</p>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary">クリック</button>
</mat-card-actions>
</mat-card>
`,
})
export class HelloComponent {}
MatButtonModuleやMatCardModuleをコンポーネントのimports配列に加えるだけで、<mat-card>やmat-raised-button属性がテンプレート内で使えるようになります。color="primary"のようなカラー属性は、あとで解説するテーマ設定と連動して配色が決まります。
実践的なユースケース
M3テーマでアプリ全体の配色を統一する
Angular Materialは、コンポーネントごとに個別スタイルを当てるのではなく、_theme.scssのようなグローバルなテーマファイルで配色・形状・密度をまとめて定義する設計になっています。M3(Material 3)のトークンシステムでは、mat.define-themeにカラー・タイポグラフィ・密度をまとめて渡すことで、アプリ全体の見た目を一箇所で管理できます。
@use '@angular/material' as mat;
$my-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$violet-palette,
),
density: (
scale: 0,
),
));
html {
@include mat.all-component-themes($my-theme);
}
primaryのパレットをmat.$violet-paletteから別の色に差し替えるだけで、ボタンやフォーム部品、ダイアログなど全コンポーネントの配色が連動して変わります。既存のM2パレットからM3へ移行したい場合は、ng generate @angular/material:m3-themeスキーマティクスが変換の下地を自動生成してくれます。
リアクティブフォームとMatFormFieldでバリデーションを表示する
フォーム入力を扱う場面では、AngularのReactiveFormsModuleとMatFormFieldModuleを組み合わせるのが定番です。入力エラーをmat-errorで表示することで、バリデーション結果を視覚的に伝えられます。
import { Component } from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'app-email-form',
standalone: true,
imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule],
template: `
<mat-form-field appearance="outline">
<mat-label>メールアドレス</mat-label>
<input matInput [formControl]="email" />
@if (email.hasError('email')) {
<mat-error>メールアドレスの形式が正しくありません</mat-error>
}
</mat-form-field>
`,
})
export class EmailFormComponent {
email = new FormControl('', [Validators.required, Validators.email]);
}
Validators.emailが検証ルールを、mat-errorが結果の表示を担当しており、両者を組み合わせることでフォームの状態がそのままUIに反映されます。バリデーションルールをValidators.minLength(8)のように変えると、mat-error側のメッセージもそれに合わせて書き換える形になります。
Angular CDKのOverlayでカスタムダイアログを作る
Angular Materialにはそのまま使えるMatDialogもありますが、見た目を完全に自由に作りたい場合は、ベースにある@angular/cdk/overlayを直接使う方法もあります。CDKはスタイルを持たない「振る舞い」だけを提供するため、独自デザインのポップアップやツールチップを組み立てる土台として使えます。
import { Component } from '@angular/core';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { MyPanelComponent } from './my-panel.component';
export class MenuTriggerDirective {
private overlayRef?: OverlayRef;
constructor(private overlay: Overlay) {}
open() {
this.overlayRef = this.overlay.create({
hasBackdrop: true,
positionStrategy: this.overlay
.position()
.global()
.centerHorizontally()
.centerVertically(),
});
this.overlayRef.attach(new ComponentPortal(MyPanelComponent));
this.overlayRef.backdropClick().subscribe(() => this.overlayRef?.dispose());
}
}
Overlay.create()で表示位置と背景(バックドロップ)の有無を指定し、attach()で任意のコンポーネントをそこに描画します。positionStrategyをconnectedTo(triggerElement)に変えると、中央固定ではなくボタンの直下に吸着するドロップダウン的な挙動に変更できます。
MatTableとページネーション・ソートを組み合わせる
一覧画面でよくある「ソートできてページ送りもできるテーブル」は、MatTableとMatSort・MatPaginatorをViewChildで接続することで実現します。
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { MatTableModule, MatTableDataSource } from '@angular/material/table';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
@Component({
selector: 'app-user-table',
standalone: true,
imports: [MatTableModule, MatSortModule, MatPaginatorModule],
template: `
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>名前</th>
<td mat-cell *matCellDef="let row">{{ row.name }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="['name']"></tr>
<tr mat-row *matRowDef="let row; columns: ['name']"></tr>
</table>
<mat-paginator [pageSize]="10"></mat-paginator>
`,
})
export class UserTableComponent implements AfterViewInit {
dataSource = new MatTableDataSource([{ name: '田中' }, { name: '佐藤' }]);
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatPaginator) paginator!: MatPaginator;
ngAfterViewInit() {
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}
}
MatTableDataSourceにsortとpaginatorを紐づけるだけで、mat-sort-headerを付けた列のクリックソートと、mat-paginatorによるページ送りが自動で連動します。表示件数を増やしたい場合は[pageSizeOptions]="[10, 25, 50]"のように選択肢を渡せば、読者側で切り替え可能なUIになります。
まとめ
Angular Materialは、Material Designに準拠したコンポーネント一式をAngular公式チームが保守してくれる、UI実装の土台として頼れるライブラリです。ボタンやフォーム部品をそのまま使うだけでなく、M3テーマでアプリ全体の配色を統一したり、Angular CDKを直接使って独自のUIを組み立てたりと、要件に応じた使い分けができるのも強みです。まずはng add @angular/materialで導入し、手元のプロジェクトでMatButtonModuleあたりから試してみてください。