🎨

Web アプリにも Material 3 の Color System を導入する

2022/10/19に公開約2,600字

Web 向けの Material 3 ライブラリはこちらのページによると、現在「対応予定」となってますが、Flutter でも使用されている新しい Color System を実装するライブラリの NPM 版が公開されていたりするので、こちらを使用して Web アプリにも Material 3 の Color System だけ導入することができます。

Material 3 の Color System についての公式ドキュメントはこちら。

https://m3.material.io/styles/color/overview

インストール

@material/material-color-utilities になります。

$ npm install @material/material-color-utilities

この記事では、公開時点で最新の v0.2.0 を使用しています。

テーマを生成する

themeFromSourceColor でシードカラーから、themeFromImage で画像からテーマを生成できます。

const seedColor = 0x6750a4;
const theme = themeFromSourceColor(seedColor);

const image = new Image();
const theme = themeFromImage(image);

第二引数では、カスタムカラーを追加できます。

themeFromSourceColor(seedColor, [
  {
    name: "custom-color",
    value: 0xff0000,
  },
]);

カスタムカラーは単にテーマに対して key:value で追加されるわけではなく、テキストカラーやコンテナカラーが一緒に生成されるようになっています。

Color rules より

また blend オプションを渡すことで、Harmonization という仕組みを適応することも可能です。

 themeFromSourceColor(seedColor, [
   {
     name: "custom-color",
     value: 0xff0000,
+    blend: true,
   },
 ]);

Harmonization を適応すると以下の画像のように、カスタムカラーを少しシードカラーに寄せることで、アプリの色合いにまとまりを持たせます。

Harmonization より

テーマを使用する

生成したテーマは applyTheme 関数に渡すことで、CSS Variable として <body> に展開されます。
(カスタムカラーは展開されないため、追加で実装する必要があります。)

applyTheme(theme);
applyTheme(theme, { dark: true }); // ダークテーマを適応する

applyTheme(theme, { target: document.documentElement }); // 展開先を変更する

各色には --md-sys-color- のプリフィックを付けてアクセスします。

.foo {
  background-color: var(--md-sys-color-primary);
  color: var(--md-sys-color-on-primary);
}

CSS in JS などで直接アクセスする場合は以下のようになります。

スキームへのアクセス:

const lightScheme = theme.schemes.light;
const darkScheme = theme.schemes.dark;

const lightPrimary = lightScheme.primary;
const lightOnPrimary = lightScheme.onPrimary;

カスタムカラーへのアクセス:
配列なのでそのままでは使いづらいかもしれません。

const lightCustom = theme.customColors[0].light;
const darkCustom = theme.customColors[0].dark;

const lightCustomColor = lightCustom.color;
const lightCustomOnColor = lightCustom.onColor;

サンプル

GitHubで編集を提案

Discussion

ログインするとコメントできます