🎨

Angular Material でカスタムカラーを使う

2021/12/15に公開

Angular Advent Calendar 2021 15 日目の記事です。

Angular Material を使う場合、デフォルトで下記のテーマが用意されています。

  • Deep Purple & Amber
  • Indigo & Pink
  • Pink & Blue-gray
  • Purple & Green

しかし、これらのカラーテーマをそのまま使うことってほとんどないですよね。コーポレートカラーやアプリケーションのイメージカラーが Material Design のカラーパレットに含まれる色だった場合はラッキーですが、なかなかそうもいきません。

今回は Angular Material における色の管理方法を交えながら、カスタムカラーを使う方法をご紹介します。

各 version

  • Angular: v13.0.0
  • Angular Material: v13.0.3

Angular Material で用意されている色の定義を見てみよう

Angular Material では こちらの_palette.scss で管理されています。

40 行目$red-paletter の定義を見てみましょう。

_palette.scss
$red-palette: (
  50: #ffebee,
  100: #ffcdd2,
  200: #ef9a9a,
  300: #e57373,
  400: #ef5350,
  500: #f44336,
  600: #e53935,
  700: #d32f2f,
  800: #c62828,
  900: #b71c1c,
  A100: #ff8a80,
  A200: #ff5252,
  A400: #ff1744,
  A700: #d50000,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $dark-primary-text,
    400: $dark-primary-text,
    500: $light-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
    A100: $dark-primary-text,
    A200: $light-primary-text,
    A400: $light-primary-text,
    A700: $light-primary-text,
  )
);

こちらのコードは Material Design のカラーパレットを表しています。

赤のカラーパレット

red-palette 直下では 50〜A700 までのカラーコードを、contract の中では 50〜A700 までのカラーが背景になったときの文字色を定義しています。カラーコードの中で 50〜900 は通常色、A100〜A700 はアクセントカラーとして使うことを想定されいてる色のようで、通常色に比べてビビットな色が定義されています。

文字色はこちらのTypography のガイドライン に沿い、文字の視認性を考慮して不透明度 87% の黒か不透明度 100%の白が指定されています。

カスタムカラーのパレットを用意する

カスタムカラーを使用したい場合は、前項で紹介したのと同じようなパレットの scss 変数を用意してあげる必要があります。色の知識なしにパレットを作成するのは難しいですが、Material Design に沿ったカラーパレットを生成してくれる Web サービスがありますのでご安心ください。
こちらのMaterial Design Palette Generatorを使用することで、簡単にカラーパレットを生成できます。

Material Design Palette Generator でパレットを生成した様子

右上の青い四角をクリックして、基準となる 500 に設定したい色を指定します。その後クリップボードのアイコンをクリックして、ANGULAR JS 2 (MATERIAL2) を選ぶと、先程見た$red-paletteのようなパレットのコードを生成してくれています。

カスタムカラーに変更してみる

早速こちらを設定してみましょう。

既存の theme css を削除する

まずng add したときに Deep Purple & Amber 等のテーマを指定した場合は、angular.json からそのテーマ用の css を削除します。対象の project のbuildtest に記述があるので、それぞれ削除しましょう。

"styles": [
- "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
  "src/style.scss"
],

custom palette を作成する

Material Design Palette Generator で生成したコードを使って custom palette を作成しましょう。

今回は 500 に#f1e332(黄色)を指定して作ってみました。

assets/_palette.scss
$custom-primary: (
  50: #fdfce6,
  100: #fbf7c2,
  200: #f8f199,
  // ...A700まで
  contrast:
    (
      50: #000000,
      100: #000000,
      200: #000000,
      // ...A700まで
    )
);

Color Theme を設定する

styles.scss に下記のように追記します。

styles.scss
@use "@angular/material" as mat;
@use "./assets/palette" as palette;

@include mat.core();

// primary に先程作成した $custom-primary を指定
$custom-primary: mat.define-palette(palette.$custom-primary);
// secondary はAngular Material のpalette からlight-blue を指定
$custom-accent: mat.define-palette(mat.$light-blue-palette, A200, A100, A400);
$custom-warn: mat.define-palette(mat.$red-palette);

$custom-theme: mat.define-light-theme(
  (
    color: (
      primary: $custom-primary,
      accent: $custom-accent,
      warn: $custom-warn,
    ),
  )
);

@include mat.all-component-themes($custom-theme);

mat.define-palette() の実装を見てみましょう。

_theming.scss
@function define-palette($base-palette, $default: 500, $lighter: 100, $darker: 700,
  $text: $default) {
  $result: map.merge($base-palette, (
    default: map.get($base-palette, $default),
    lighter: map.get($base-palette, $lighter),
    darker: map.get($base-palette, $darker),
    text: map.get($base-palette, $text),

    default-contrast: get-contrast-color-from-palette($base-palette, $default),
    lighter-contrast: get-contrast-color-from-palette($base-palette, $lighter),
    darker-contrast: get-contrast-color-from-palette($base-palette, $darker)
  ));

  // For each hue in the palette, add a "-contrast" color to the map.
  @each $hue, $color in $base-palette {
    $result: map.merge($result, (
      '#{$hue}-contrast': get-contrast-color-from-palette($base-palette, $hue)
    ));
  }

  @return $result;
}

引数にカラーパレットとその中でデフォルトの色・デフォルトの色の明るいバージョンと暗いバージョン・テキストの色がありますが、それぞれにデフォルト値が設定されています。なので先程設定した$custom-primary は引数が 1 つで十分ですが、アクセントカラーを使う$custom-accent では引数として 3 色渡しています。

// 自動で500, 100, 700 が使われる
$custom-primary: mat.define-palette(palette.$custom-primary);
// 500, 100, 700 以外のアクセントカラーを使いたいので3つ指定する
$custom-accent: mat.define-palette(mat.$light-blue-palette, A200, A100, A400);

これでカスタムカラーを指定することができました!結果を見てみましょう!

カスタムカラー使用例

MATCH みたいな爽やかな色合いになりましたね!Angular Material を使う以上は Material Design のカラーパレットを使うに越したことはありませんが、別の色を使う必要がある場合はこのように設定して実装していきましょう!

GitHubで編集を提案

Discussion