prefers-color-schemeで行うダークテーマ配色の対応

## これはなに

育休で長いお休みをいただいている間に、[Qiitaがダークテーマに対応していました。](https://blog.qiita.com/release-theme/)
長い間、開発メンバーでも対応していきたいねと言っていたので、正式リリースされたのを見たときは感無量でした。

対応の概要は下記の記事で @xrxoxcxox が解説してくれています。

https://qiita.com/xrxoxcxox/items/9fac826a2e1c8526aa50

いざ復職してダークテーマ対応を後追いで把握していくときに、 メディア特性の `prefers-color-scheme` について調べました。

この記事では、 `prefers-color-scheme` を使ったダークテーマの配色の仕方を簡単にまとめたいと思います。

## `prefers-color-scheme` とは

MDNによると

>prefers-color-scheme は CSSのメディア特性で、ユーザーがシステムに要求したカラーテーマが明色か暗色かを検出するために使用します。

https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-color-scheme

つまり、`prefers-color-scheme` システム設定で指定したカラーモードに一致した配色を提供できます。

## 基本的な使い方

### ライトテーマ

`light` を指定します。
ユーザーがシステム設定で、ライトテーマを選択したか、アクティブな設定を示さなかったことを示します。

```css
@media (prefers-color-scheme: light) {
  .contents {
    background: #fff;
    color: #555;
  }
```

## ダークテーマ

`dark` を指定します。
ユーザーがシステム設定で、ダークテーマを設定したことを示します。


```css
@media (prefers-color-scheme: dark) {
  .contents {
    background: #333;
    color: #fff;
  }
```

## Qiitaではこうしていた

### デザイントークンの更新

カラーパレットに、エイリアストークン（color alias）が追加されました。
エイリアストークンが追加されたことで

- `@media (prefers-color-scheme: dark)` の指定の削減
- ライトテーマ・ダークテーマ共通で利用できる命名

ができるようになりました。

```css
:root {
    /* color global */
    --color-gray-0: #fff;
    --color-gray-5: #f9fafa;
    --color-gray-10: #f5f6f6;
    --color-gray-20: #edeeee;
    --color-gray-30: #dfe0e0;
    --color-gray-40: #bcbdbd;
    --color-gray-50: #9c9e9e;
    --color-gray-60: #7a7d7d;
    --color-gray-70: #5e6060;
    --color-gray-80: #494b4b;
    --color-gray-90: #3a3c3c;
    --color-gray-100: #2f3232;
    /* ... */
    
    /* color alias */
    --color-background: var(--color-gray-10);
    --color-surface: var(--color-gray-0);
    --color-surface-variant: var(--color-gray-20);
    --color-text-disabled: rgb(0 0 0 / 38%);
    --color-text-medium-emphasis: rgb(0 0 0 / 60%);
    --color-text-high-emphasis: rgb(0 0 0 / 87%);
}

@media (prefers-color-scheme: dark) {
   :root{
       --color-background: var(--color-gray-110);
       --color-surface: var(--color-gray-100);
       --color-surface-variant: var(--color-gray-80);
       --color-text-disabled: rgb(255 255 255 / 38%);
       --color-text-medium-emphasis: rgb(255 255 255 / 60%);
       --color-text-high-emphasis: rgb(255 255 255 / 87%);
   }
}
```
※実際にはダークテーマ用は別ファイルになっております。

### 各要素での指定

```css
.main {
    background-color: var(--color-background);
    color: var(--color-text-high-emphasis);
}

.article{
  background-color: var(--color-surface);
}
```


ここまでのより詳しい対応内容や背景は、先に紹介した下記の記事をご覧ください :pray: 

https://qiita.com/xrxoxcxox/items/9fac826a2e1c8526aa50

### すべての配色がワンソースで行くわけではない

カラーパレットにエイリアストークン（color alias）が追加されたことで、基本的な実装はメディア特性を必要としていません。
が、時には個別に指定が必要になります。

例えば、Qiitaの記事でいうと下記の `info` など、エイリアストークンに指定がない背景色のUIなどが該当します⏬

:::note info
このようなエイリアストークンに指定がない背景色のUIでは個別指定が必要になります。
:::

こういったUIのときには、 `prefers-color-scheme` でカラーの指定が必要になります。

とはいえ、頻繁に実装するものではありません。
CSSもそこまで肥大化せずに実装することができていると感じています。


## サポートブラウザ

`prefers-color-scheme` のサポートは、2023年12月時点でMDNを見ると下記のようになっています。

![スクリーンショット 2023-12-23 22.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215239/ee90edce-01f3-8fd8-ee81-e9d34f801cd2.png)

## 参考

- [prefers-color-scheme - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-color-scheme)
- [12 年続くサービスにダークテーマ UI を導入した #CSS - Qiita](https://qiita.com/xrxoxcxox/items/9fac826a2e1c8526aa50)