CSS の 色関数 について

## 目的
WEB 制作をされている方なら、CSS の color (関連) プロパティおよび色関数は
必ず使われると思います。
そんな color プロパティ / 色関数、その歴史と共に改めて学習したいと思います。

## 「色」を知ることは人を知ること
最初に「色」に目を向けてみましょう。

歴史上初めて「色」というものを科学的に体系的に論理立てたのは、
リンゴでお馴染みアイザック・ニュートンでした。
彼は 1704 年の著書「Opticks（光学）」において、
白色光はあらゆる色の光が混ざったものであると言及します。

また 1894 年にはヘルマン・フォン・ヘルムホルツがトマス・ヤングの説を発展させ、
色覚理論を発表。この理論は、カラーフィルム・カラーテレビ・PCディスプレイにも応用されることになります。

「色」と「インターネット」に関係する歴史的なことといえば、下記もあります。
- 1963年 世界初の実用可能な GUI を搭載した防空管制システム (SAGE) が開発
- 1989年に欧州原子力機構 (CERN) のティム・バーナーズ=リーが WWW (正確には前身)を提案

これほどまでに、"色"、"人"、そして"コンピューター"は深い歴史があるわけですね。
(当たり前のことですが。)

## 色関数ご存知ですか ?
このままですと本題から外れ過ぎてしまうので、CSS に戻りましょう。

突然ですが、CSS での色関数をいくつご存知でしょうか。

|定義方法|記述例|
|-|-|
|RGB|rgb(214, 122, 127)|
|RGB 16進数表記|#00ff00|
|色キーワード|blue|
|HSL|hsl(30, 100%, 50%)|
|HWB|hwb(12 50% 0%)|
|Lab|lab(31% -12 -4)|
|LCH|lch(31% 13 198)|
|Oklab|oklab(40% -0.036 -0.010)|
|Oklch|oklch(40% 0.037 195)|

いかがですか ? 

## CSS における color と色関数
### CSS1
「color」に関するプロパティは、すでに 1996 年の CSS1 から存在していました。

:::note
[W3C によると](https://www.w3.org/TR/CSS1/) CSS1 時点での全プロパティ数は 53 個 !!
今から考えると相当少なく感じますね。

ちなみに、CSS1 の全てのプロパティは以下になります。
<details>
<summary>CSS1 のプロパティ</summary>
<div>

- background  
- background-attachment  
- background-color  
- background-image  
- background-position  
- background-repeat  
- border  
- border-bottom  
- border-bottom-width  
- border-color  
- border-left  
- border-left-width  
- border-right  
- border-right-width  
- border-style  
- border-top  
- border-top-width  
- border-width  
- clear  
- color  
- display  
- float  
- font  
- font-family  
- font-size  
- font-style  
- font-variant  
- font-weight  
- height  
- letter-spacing  
- line-height  
- list-style  
- list-style-image  
- list-style-position  
- list-style-type  
- margin  
- margin-bottom  
- margin-left  
- margin-right  
- margin-top  
- padding  
- padding-bottom  
- padding-left  
- padding-right  
- padding-top  
- text-align  
- text-decoration  
- text-indent  
- text-transform  
- vertical-align  
- white-space  
- width  
- word-spacing  
</div>
</details>
:::

色関数については、CSS1 では下記の方法によって定義することができます。
(参考: [Cascading Style Sheets, level 1](https://www.w3.org/TR/CSS1/#color-units))

|定義方法|記述例|
|-|-|
|キーワード色名*1|color: olive|
|16進表記の RGB 値|color: #ff0000|
|関数表記の RGB 値|color: rgb(100%, 0%, 0%)|  

さすがに基本中の基本ですね。
なお、キーワード色は全16色。 Windows の VGA パレットに準拠しています。


### CSS2
1998 年に勧告され、さまざまな刷新がされた CSS2 ですが、
color 関連での大きな変更はありませんでした。

### CSS Color Module 3
CSS3 からは[モジュール単位](https://www.w3.org/Style/CSS/current-work)で開発を進めることとなり、
color に関しては、2011 年に CSS Color Module Level 3 が勧告されました。
この更新によって、color には新たに下記の色関数が実装されました。
(参考: [CSS Color Module Level 3](https://www.w3.org/TR/css-color-3/))

|定義方法|記述例|
|-|-|
|RGBA|color: rgba(255,0,0,1)<br>color: rgb(100%,0%,0%)|
|HSL / HSLA|color: hsl(120, 100%, 50%)|
|transparent| background-color: transparent|
|currentColor|border: 2px solid currentColor|

### CSS Color Module 4
2022 年に 草案が発表された CSS Color Module Level 4。
将来、新たに追加されるであろう色関数はこちら。
(参考: [CSS Color Module Level 4](https://www.w3.org/TR/css-color-4/))

|定義方法|記述例|
|-|-|
|16進表記の RGB 値の透過指定|color: #0000ffcc|
|HWB|hwb(150 20% 10%)|
|lab|lab(29.567% 68.298 -112.0294)|
|lch|lch(51.2345% 21.2 130)|
|Oklab|oklab(66.016% -0.1084 0.1114);|
|Oklch|oklch(40.101% 0.12332 21.555);|

(個人的には)普段使っていない関数も増えてきました。

## 色関数増加のわけ
色関数が増加した理由としては、以下のことが考えられそうです。

1. 直感的な読みやすさを向上させたいから
2. 色の表現技術が向上したから
3. "知覚的に均等"にしたい

### 1. 直感的な読みやすさを向上させたいから
`#ff0000`,`rgb(255,255,0)`など極端な色については判断できますが、
例えば、`rgb(189,183,107)`、`#bdb76b`などでは直感的に判断できるでしょうか。

CSS Color Module 3 以上から作成された色関数では、
この問題の解決を図っているようです。

### 2. 色の表現技術が向上したから
もちろん、ディスプレイの進化も色関数の増加の要因になっています。

ディスプレイが表現できる色の範囲を定義する「色空間」。
従来の色空間として代表的なものとして sRGB や Adobe RGB が挙げられますが、
色空間も新たに更新されております。

例えば、Apple が策定した Display P3 があります。
sRGBが表現する色全てを含んでおり、かつ、表現可能な色合いが約 25% 拡大しています。
(Apple 製品では 2016年発売のiPhone 7、iPad Pro/Air(第3世代)/ mini(第5世代)などから Display P3 対応となっているそうです。)

このように表現できる色の拡大により、色関数も増えているようです。

### 3. "知覚的に均等"にしたい
>「知覚的に均等」とは、色の値が同じだけ変化したとき、人間がそれを見たときに感じられる変化も等しいことを意味する。
> ([Lab色空間 - Wikipedia](https://ja.wikipedia.org/wiki/Lab%E8%89%B2%E7%A9%BA%E9%96%93)]

彩度・明度の数値を同じように揃えた色でも、
色相が違うと人間の目には明るさが異なっているように見えるということです。

<img width="100" alt="hsl_60_100_50" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/944501/c549602e-2b68-174e-65e4-89d68976c1ad.png">
<img width="100" alt="hsl_290_100_50" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/944501/f59568d3-7a00-d4ec-0169-1fb51f096716.png">

上記、左は `hsl(60 100% 50%)`、右は `hsl(290 100% 50%)` です。
同じ彩度と明度ですが、左の方が明るく見えませんか?

Lab や LCH 、そして　Oklab と Oklch　では、この均等性が改善されています。

## 各色関数の使い方
では、最後に各色関数とその使い方をざっと見ていきましょう。

### HSL
> hsl() 関数表記は、 sRGB 色を色相、彩度、明度の成分 によって表現します。オプションのアルファ成分は、そ の色の透明度を表します。
> ([hsl() - MDN](https://developer.mozilla.org/ja/docs/Web/CSS/color_value/hsl))
```
/* 空白区切りの値の構文 */
hsl(hue saturation lightness) hsl(hue saturation lightness / alpha)
hsl(hue, saturation, lightness) hsl(hue, saturation, lightness, alpha)
hsl(360, 100%, 50%),
```

### HWB
> hwb() 関数記法は、指定された色を色相、白色度、黒 色度によって表現するものです。オプションのアル ファ成分は、色の透明度を表します。
> ([hwb() - MDN](https://developer.mozilla.org/ja/docs/Web/CSS/color_value/hwb))
```
hwb(194 0% 0%)
hwb(194 0% 0% / .5)
```

### lab
> lab() 関数記法は、指定された色を CIE L*a*b* 色空間で表現する。 Lab は人間が見ることのできる色の範囲をすべて表します。
> ([lab() - MDN](https://developer.mozilla.org/ja/docs/Web/CSS/color_value/lab))

「CIE Lightness(CIE 明度)」「a(緑から赤への軸)」「b(青 から黄への軸)」を指定しています。

```
lab(29.2345% 39.3825 20.0664)
lab(52.2345% 40.1645 59.9971)
lab(52.2345% 40.1645 59.9971 / .5)
```

### lch
> lch() 関数記法は、指定された色を LCH 色空間で表現するものです。 これは lab() と同じ L 軸を持っていますが、極座標の C (彩度)
と H (色相)を使用します。
> ([lcv() - MDN](https://developer.mozilla.org/ja/docs/Web/CSS/color_value/lch))

```
lch(29.2345% 44.2 27)
lch(52.2345% 72.2 56.2)
lch(52.2345% 72.2 56.2 / .5)
```

### Oklab / Oklch
> 指定された色を、人間の目による色の知覚方法を模倣しようとするOKlab色空間で表現する。この oklab() は OKlab 色空間上のデカルト座標系、 a 軸と b 軸で動作します。極座標系、彩度、色相が必要な場合は、 oklch() を使用してください。
> ([oklab() - MDN](https://developer.mozilla.org/ja/docs/Web/CSS/color_value/oklab))

> 指定された色を OKLCH 色空間で表現します。これは oklab() と同じ L 軸を持っていますが、極座標 C （彩度）と H （色相）を使用します。
> ([oklch() - MDN](https://developer.mozilla.org/ja/docs/Web/CSS/color_value/oklch))

- Lab と LCH の下記問題を解消するために 2020 年末に誕生しました。
    - h(色相)の値が 270 から 330 の青色の領域での直線性に問題があり、高い彩度から彩度を下げていくと紫みが増します。
    - Lab / LCH の色相は HSL や HWB よりは優れているが、均等性は完全ではありません。
    - 高彩度の色になると彩度の変化が目立たなくなります。

```
oklab(40% -0.04 -0.01)
oklab(40% -0.04 -0.01 / 0.5)
oklab(40% -0.04 -0.01 / 50%)

oklch(40% 0.04 194)
oklch(40% 0.04 194 / 0.5)
oklch(40% 0.04 194 / 50%)
```

## まとめ
全体的に駆け足になってしまいましたが、
現在は CSS1, CSS2.1 の時と違い、色の表現についても技術の向上を確認できました。
今までは、ほぼ RGB値やRGB値の 16 進数表記のみを使っていましたので、
他のものも積極的に使っていきたいと思えるようになりました。

ありがとうございました。

## 参考

https://cpaa.or.jp/color-mechanism/

https://www.w3.org/ja/press-releases/1998/css2/

https://griponminds.jp/blog/relearn-css-color/

https://qox.jp/blog/css-color-space-lv4/