ベースライン CSS 機能を使用したカラーテーマ

David A. Herron
David A. Herron

公開日: 2025 年 12 月 11 日

サイトを構築または再設計したいと考えているとします。いくつかのコアカラーを念頭に置き、それらの色に基づいてテーマをすばやく実装する方法を検討しているかもしれません。

メインの色だけでなく、アクション、ホバー状態、エラーの色、その他のユーザー インターフェースに必要な色も必要になります。ライトモードとダークモードのオプションはどうなりますか?突然、たくさんの色が必要になり、圧倒されることがあります。

幸いなことに、サイトを定義するカラー トークンに関連するパレットの構築や、カラーモードの切り替えに関しては、Baseline の機能が多くの作業を代行してくれます。これらの手法の一部は、架空の Baseline Radio サイトのカラーテーマのプレイリストである注目のデモで確認できます。

相対色でベースを構築する

テーマのメインカラーのアイデアがある場合は、基本的なカラー理論と CSS の相対色構文を使用して、テーマで使用するカラーパレットをすばやく生成できます。

たとえば、ベースカラーがティール系の色の場合、まず好みのカラー形式で定義します。その後、任意のカラー関数を使用して、ベースカラーを基準とした新しいカラーを作成できます。

html {
  --base-color: oklch(43.7% 0.075 224);
}

--base-color カスタム プロパティは、oklch() カラー関数を使用して作成されます。OkLCh は Oklab 色空間の円柱形式で、L(明度)、C(彩度)、H(色相)の 3 つのチャンネルの値と、透明度を制御するオプションのアルファ チャンネルを定義します。

OkLCh は、知覚的な均一性を提供するように設計されているため、このタイプの色の操作に適した形式です。たとえば、色の色相のみを調整した場合、結果の色は元の色と知覚される明度と彩度が類似している必要があります。これは、予期しないコントラストの問題を回避するうえで特に役立ちます。

--base-color の明度と彩度を維持したまま、色相を両方向に 120 度調整して、トライアド パレットを作成できます。

html {
  /* ... */
  --triadic-color-primary: oklch(from var(--base-color) l c calc(h + 120));
  --triadic-color-secondary: oklch(from var(--base-color) l c calc(h - 120));
}

この例に示すように、相対色構文では、from キーワードで元の色(この例では --base-color)を参照する色関数を使用し、選択した出力色に基づいて色空間の各チャネルを調整します。この例では、出力色も OkLCh になります。

出力結果では、--accent-color には濃いピンク、--highlight-color にはゴールドのシェードが返されます。どちらも元の --base-color と同じ明度と彩度になります。

html {
  /* ... */
  --accent-color: var(--triadic-color-primary);
  --highlight-color: var(--triadic-color-secondary);
}

  html {
    /* Input color in the rgb color space*/
    --base-color: teal;

     /* Output color in oklch. Computes to oklch(0.543123 0.0927099 314.769) */
     --triadic-color-primary: oklch(from var(--base-color) l c calc(h + 120));
  }

補色では、色相角に 180 度が追加されます。

html {
  /* ... */
  --complement-color: oklch(from var(--base-color) l c calc(h + 180));
  --border-highlight: var(--complement-color);
}

UI のホバー状態では、特定の色を明るくしたバージョンを出力したい場合があります。つまり、明度チャネルの値を大きくします。アクティブな状態では、アルファ チャンネルを調整して透明度を追加したり、明度チャンネルの値を小さくして暗くしたりできます。

html {
  /* Darken the --base-color by 15% */
  --base-color-darkened: oklch(from var(--base-color) calc(l * 0.85) c h);
  /* Assign this color a meaningful variable name */
  --action-color: var(--base-color-darkened);
  /* Lighten the --action-color by 15% */
  --action-color-light: oklch(from var(--action-color) calc(l * 1.15) c h);
  /* Darken the --action-color by 10% */
  --action-color-dark: oklch(from var(--action-color) calc(l * 0.9) c h);
}

ここでは、--base-color から --action-color を導出し、ボタンとリンクに使用しています。--action-color には明るい色と暗い色の 2 つのバリエーションがあり、--action-color--base-color とは異なる別の色を基準とするように変更された場合でも、これらのバリエーションは適用されます。

calc() などの数学関数を使用するか、チャンネル全体を新しい値に置き換えることで、チャンネルを調整できます。変更されていないチャンネルは、それぞれの文字で表されます(たとえば、変更されていない明度の値は l で表されます)。

color-mix() で色を混ぜる

他の色のバリエーションについては、同様のアプローチで --base-color カスタム プロパティの他のチャネルを調整できます。また、color-mix() を使用して、デザインの他のアスペクトにベースカラーのヒントを追加することもできます。

--border-color は、ベースカラーと名前付きカラー greyoklab 色空間で補間したものです。色補間メソッドとして使用すると、知覚的に均一な結果が得られます。

html {
  --base-mix-grey-50: color-mix(in oklab, var(--base-color), grey);
  --border-color: var(--base-mix-grey-50);
}

デフォルトでは、各色が 50% の割合で表示されますが、割合を調整することで、どちらかの色をより目立たせたり、目立たなくしたりできます。

html {
  --background-mix-base-80: color-mix(in oklab,
    var(--background-color) 80%,
    var(--base-color));
  --surface-light: var(--background-mix-base-80);
}

要素に色を追加する代わりに、相対色構文を使用して彩度チャンネルを調整することもできます。お問い合わせフォームのテキスト入力の枠線は、フォーカスされているときに少しカラフルになります。

[data-input*="text"] {
  --focus-ring: transparent;
  /* ... */
  &:focus {
    --focus-ring: oklch(from var(--border-color) l calc(c + 0.1) h);
  }
}

ライトモードとダークモードを有効にする

使用する色のセットができたら、ライトモードとダークモードで異なる色を効率的に適用する方法が必要になります。

color-scheme プロパティでライトモードとダークモードのサポートを通知する

color-scheme プロパティを使用すると、サイトを「ライト」モード、「ダーク」モード、または両方のモードで表示できることをブラウザに即座に伝えることができます。このプロパティは、要素を快適にレンダリングできるカラースキームをブラウザに伝えます。

 html {
   color-scheme: light dark;
}

:root 疑似要素または html 要素に color-scheme: light dark を設定する:

  • ページがライトモードまたはダークモードでの表示に対応していることをブラウザに伝えます。
  • ブラウザのユーザー インターフェースのデフォルトの色を、それぞれのオペレーティング システムの設定に合わせて変更します。

ページがライトモードとダークモードをサポートしていることをユーザー エージェントに事前に通知するには、ドキュメントの <head><meta> 要素を追加して、カラースキームの切り替えのサポートをシグナルで伝えることもできます。

<head>
  <!-- ... -->
   <meta name="color-scheme" content="light dark">
</head>

light-dark() 関数を使用して「light」と「dark」のバリエーションを設定する

作成者は、prefers-color-scheme @media クエリを使用してページの色を設定することに慣れているかもしれません。

@media (prefers-color-scheme: light) {
  html {
    --background-color: oklch(95.5% 0 162);
    --text-color: black;
  }
}

@media (prefers-color-scheme: dark) {
  html {
    --background-color: oklch(22.635% 0.01351 291.83);
    --text-color: white;
  }
}

これは、作成者が制御する色やスタイルには有効ですが、前のセクションで説明したように、ブラウザ UI の色を更新するには color-scheme が必要です。

prefers-color-scheme クエリでページの色を変更すると、各モードの色を個別に定義する必要があるため、コードの重複も発生します。

ただし、ページ全体(または特定の要素)に color-scheme を設定すると、light-dark() 関数を使用して、各モードの色を 1 行のコードで設定できます。

この関数は 2 つの色を受け取ります。1 つ目はカラーパターンが「ライト」に設定されている場合に使用され、2 つ目はカラーパターンが「ダーク」に設定されている場合に使用されます。

html {
  color-scheme: light dark;
  /* Color custom property values for both light and dark modes */
  --base-color: light-dark(oklch(43.7% 0.075 224), oklch(89.2% 0.069 224));
  --background-color: light-dark(oklch(95.5% 0 162), oklch(22.635% 0.01351 291.83));
  --accent-color: oklch(from var(--base-color) l c calc(h + 120));
  --active-color: light-dark(var(--action-color-light), var(--action-color-dark));
  /* ... */
}

カスタム プロパティと同様に、色の light-dark() 設定はグローバルに設定することも、特定のコンポーネント内で設定することもでき、必要に応じて他の場所で使用できます。

/* custom property usage */
body {
  background-color: var(--background-color);
  /* ... */
}

:any-link {
  /* ... */
  text-decoration-color: var(--accent-color);
}

組み込みのテーマ切り替え機能でユーザーが制御できるようにする

ユーザーのデフォルトのシステムやブラウザの色の設定に合わせてテーマを調整できるのは素晴らしいことですが、さらに一歩進んで、サイトの閲覧者がこれらのデフォルトの色の設定をオーバーライドできるようにすることもできます。

<html> 要素の data-scheme 属性を更新するテーマ切り替えを作成する場合、同じ属性を使用して CSS で color-scheme を変更できます。

html {
  color-scheme: light dark;

  &[data-scheme="light"] {
    color-scheme: light;
  }

  &[data-scheme="dark"] {
    color-scheme: dark;
  }

  &[data-scheme="green"] {
      --base-color-light: oklch(48.052% 0.11875 151.945);
      --base-color-dark: oklch(92.124% 0.13356 151.558);
      color-scheme: light dark;
   }
}

data-scheme="light"data-scheme="dark" は、それぞれのカラーモードでのみページを表示します。data-scheme="green" はどちらのモードでも表示でき、--base-color を緑の色合いに変更することもできます。他のほとんどの色は --base-color に基づいているため、これによりまったく新しいパレットが作成されます。

@property でカスタム プロパティを登録する

これまでのデモでは、色は標準のカスタム プロパティとして設定されていました。@property ルールでプロパティを登録して、型チェックのメリットを活用することもできます。

--base-color はインターフェースの他の多くの色のベースとして使用されるため、常に色であり、フォールバック値があることを確認することをおすすめします。

@property --base-color-light {
  syntax: '<color>';
  inherits: false;
  initial-value: oklch(43.7% 0.075 224);
}

@property --base-color-dark {
  syntax: '<color>';
  inherits: false;
  initial-value: oklch(89.2% 0.069 224);
}

html {
  --base-color: light-dark(var(--base-color-light), var(--base-color-dark));
}

これにより、--base-color が誤って無効な値に変更された場合でも、@property ルールで設定された initial-value に常にフォールバックされます。

このように特定のプロパティを登録すると、linear-gradient() の色をスムーズにアニメーション化することもできます。

.main-heading {
  background: linear-gradient(in oklch 90deg, var(--text-color) 50%, oklch(from var(--base-color) l c var(--header-hue)));
  background-clip: text;
  color: transparent;
  animation: header-hue-switch 5s ease-in-out infinite alternate;
}

.main-heading には、background-clip プロパティで透明なテキストを通して表示される linear-gradient() の背景があります。

テキストの一部に hue が表示されます。これは、相対色構文を使用して、チャンネル値 26.67 から 277 にアニメーション表示されます。

@keyframes header-hue-switch {
  from {
    --header-hue: 26.67;
  }

  to {
    --header-hue: 277;
  }
}

登録済みの --header-hue カスタム プロパティを使用すると、ブラウザはこのカスタム プロパティが数値であることを認識しているため、アニメーションをスムーズに実行できます。

@property --header-hue {
  syntax: '<number>';
  inherits: false;
  initial-value: 100;
}

登録されていないカスタム プロパティの場合、ブラウザは --header-hue のデータ型を認識できないため、数値への移行は離散アニメーションとなり、状態間の移行が徐々に補間されずにジャンプします。

まとめ

新しい Baseline ツールを使用すると、調整可能なカラーパレットをすばやく作成し、カラー変数の作成をより効率的に行うことができます。ただし、無限の色のオプションと組み合わせについては、ご自身で悩む必要があります。

このようにパレットを動的に作成すると、柔軟性が高まります。ブランディングのベースカラーを変更する必要がある場合は、--base-color を更新するだけで、テーマの残りの部分はそのカラーから派生します。また、音楽再生機能を追加する場合、現在再生中の曲に合わせてベースカラーを動的に変更することもできます。

クレジット

テーマ切り替えロジックは、Adam Argyle 氏のテーマ切り替えコンポーネントを参考にしています。