【超簡単】Angular Materialのスタイルをダークモードにする

2019.11.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも!大阪オフィスの西村祐二です。

iphoneやいろんなアプリでダークモードが搭載されてきており、ちょっとしたブームになっているかと思います。よく使うAngular Materialはどうなのかなと思って調べたら、意外と簡単にできたので、設定方法などご紹介したいと思います。

Angular Materialとは

Angular公式が提供するデザインUIフレームワークです。

Bootstrapのようなイメージをもってもらうと良いかと思います。

これを使うと簡単にマテリアルデザインなアプリケーションを作ることができます。

忙しい人のために、早速Dark Modeにする

Angular Material導入済みのAngularアプリケーションのstylesファイルに下記を追加します。

src/styles.scss

@import '~@angular/material/theming';
@include mat-core();

$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);
$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

.unicorn-dark-theme {
  @include angular-material-theme($dark-theme);
}

ダークモードにしたい範囲にunicorn-dark-themeのクラスを設定しましょう。

これでダークモードになります。とても簡単ですね。

src/app.component.html

<app-main class=unicorn-dark-theme>
...
</app-main>

下記のようにスタイルがダークモードに変化します。

実際は、ボタンなどで通常モードとダークモードで切り替えたいと思うので、そんなときは下記のようにバインディングしてボタンクリックでクラスをつけたりはずしたりするのが良いかと思います。

<app-main [class.unicorn-dark-theme]="isDark">
  <button (click)="isDark = !isDark">ダークモードに切り替え</button>

解説

設定したスタイルについて簡単に解説します。

src/styles.scss

// テーマ操作関数をライブラリからインポートします
@import '~@angular/material/theming';

// Angular Material の共通スタイルを読み込みます
@include mat-core();

// 色定義します
// オプションは hueのカラーパレットで色コード指定します
// 参照: https://material.io/design/color/ and https://material.io/tools/color/
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);

// カスタムテーマを適用
$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

// クラスに設定
.unicorn-dark-theme {
  @include angular-material-theme($dark-theme);
}

試してみる

環境

Angular CLI: 8.3.18
Node: 12.13.0
OS: darwin x64
Angular: 8.2.13
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.803.18
@angular-devkit/build-angular     0.803.18
@angular-devkit/build-optimizer   0.803.18
@angular-devkit/build-webpack     0.803.18
@angular-devkit/core              8.3.18
@angular-devkit/schematics        8.3.18
@angular/cdk                      8.2.3
@angular/cli                      8.3.18
@angular/material                 8.2.3
@ngtools/webpack                  8.3.18
@schematics/angular               8.3.18
@schematics/update                0.803.18
rxjs                              6.4.0
typescript                        3.5.3
webpack                           4.39.2

簡単なAngular Materialを使ったAngularアプリケーションを作成します。

CLIからアプリケーションを生成します

$ npm install -g @angular/cli
$ ng new material-dark-mode --routing --style scss
$ cd material-dark-mode
$ ng add @angular/material
Indigo/Pinkを選択
他はenter
$ ng add @angular/cdk

コンポーネントを作成

サイドナビを作成
$ ng generate @angular/material:nav nav

ダッシュボードを作成
$ ng generate @angular/material:dashboard dashboard

コンポーネントを組みあせて、画面を作っていく

src/app.component.html

<app-nav>
  <app-dashboard></app-dashboard>
</app-nav>

src/app/nav/nav.component.html

<mat-sidenav-container class="sidenav-container">
  <mat-sidenav #drawer class="sidenav" fixedInViewport
      [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
      [mode]="(isHandset$ | async) ? 'over' : 'side'"
      [opened]="(isHandset$ | async) === false">
    <mat-toolbar>Menu</mat-toolbar>
    <mat-nav-list>
      <a mat-list-item href="#">Link 1</a>
      <a mat-list-item href="#">Link 2</a>
      <a mat-list-item href="#">Link 3</a>
    </mat-nav-list>
  </mat-sidenav>
  <mat-sidenav-content>
    <mat-toolbar color="primary">
      <button
        type="button"
        aria-label="Toggle sidenav"
        mat-icon-button
        (click)="drawer.toggle()"
        *ngIf="isHandset$ | async">
        <mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
      </button>
      <span>material-dark-mode</span>
    </mat-toolbar>
    <!-- Add Content Here -->
    <ng-content></ng-content>
  </mat-sidenav-content>
</mat-sidenav-container>

ローカル実行した画面を確認します。下記画面が出力されればOKです。

$ ng serve

ダークモードの設定

はじめに書いた設定を追加しダークモードの設定をしていきます。

src/styles.scss

/* You can add global styles to this file, and also import other style files */

@import '~@angular/material/theming';
@include mat-core();

$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);
$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

.unicorn-dark-theme {
  @include angular-material-theme($dark-theme);
}

html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }

ボタンを配置してボタンクリックで切り替えるようにしました。

<app-nav  [class.unicorn-dark-theme]="isDark">
    <button (click)="isDark = !isDark">ダークモードに切り替え</button>
  <app-dashboard></app-dashboard>
</app-nav>

注意点

たまにダークモードにならないコンポーネントがありますので、導入する際は事前に確認したほうが良いかと思われます。

例えば、下記のようなドラッグ・アンド・ドロップできるコンポーネントは今のバージョンではダークモードになっていませんでした。

さいごに

Angular Materialのスタイルをダークモードにする方法を紹介しました。

簡単にできるので、興味のある方は是非試してみてください。

誰かの参考になれば幸いです。