Kodokon kodokon.com

色と高度な関数: oklch、color-mix、min/max

知覚的な色空間、相対色構文、そして型付きの数学関数を活用し、ブラウザが計算してくれるデザインシステムを構築しましょう。

10 分 · 3 問

このレッスンを Kodokon で開く

hsl() の構造的な欠陥は、その明度が知覚的でないことです。hsl(60 100% 50%)(黄色)はまばゆく見えるのに、hsl(240 100% 50%)(青)は暗く見えます。Lは同じなのにです。oklch はこれを修正します。その L 成分(0から1)は知覚される明度を測り、C はクロマ(絶対的な彩度、0からおよそ0.37)、H は色相角です。Lを一定に保ったままHを変えれば、知覚される明るさが保たれます。パレットのバリエーションがついに予測可能になるのです。相対色構文(from)と組み合わせれば、ブラウザはあなたのホバー、ミュート、ダークのバリアントを自ら導き出してくれます。

CSS
:root {
  --brand: oklch(0.65 0.19 255);
  --dark: oklch(from var(--brand) calc(l - 0.15) c h);
  --muted: oklch(from var(--brand) l calc(c / 2) h);
  --accent: oklch(from var(--brand) l c calc(h + 180));
}
たった1つのソースカラーから、計算された3つの派生色。l、c、h の各チャンネルがローカル変数として公開されます。

oklch は、sRGB色域の外側、あるいはDisplay-P3の外側にある色さえ記述できます。画面がそれらを表示できないとき、ブラウザは何をするのでしょうか?チャンネルごとの乱暴なクリップではありません。仕様は、明度と色相を保ちながらクロマを徐々に減らし、色が対象の色域に収まるまで続ける色域マッピングを規定しています。@media (color-gamut: p3) を使えば、広色域の画面を明示的に対象にできます。もう1つの混色ツールが color-mix() です。その第1引数、すなわち補間空間は、結果を本当に変えます。青と黄色を in srgb で混ぜると灰色になりますが、in oklch では鮮やかな色相を通り抜けます。

CSS
.badge {
  background: color-mix(in oklch, crimson 70%, white);
  border-color: color-mix(
    in oklch,
    var(--brand),
    transparent 60%
  );
}
transparent と混ぜると、色を rgba として複製することなく半透明のバリアントが得られます。

min()max()clamp()型付きの数学関数です。パース時には両立しない単位(rem + vw)を混在させられます。解決はビューポートが判明した使用値の段階で行われるからです。clamp(MIN, VAL, MAX)max(MIN, min(VAL, MAX)) と厳密に等価です。そこから導かれる仕様上の帰結として、MINがMAXを超える場合はMINが勝ちます。フルイドタイポグラフィでは、中央の値に必ず rem 成分を含めましょう。rem を含まない font-size: clamp(1rem, 2.5vw, 3rem) はユーザーの文字ズームを無視してしまい、これは正真正銘のアクセシビリティ問題です。

CSS
h1 {
  font-size: clamp(1.5rem, 1.1rem + 2vw, 3rem);
}
.sidebar {
  width: min(30%, 20rem);
  padding-left: max(1rem, env(safe-area-inset-left));
}
アクセシブルなフルイドタイポグラフィと、モバイル画面のノッチを尊重する余白。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. oklch が hsl に対して提供する決定的な利点は何ですか?
    • 書くのがより短い構文
    • 色相が変わっても知覚的に均一なL明度
    • sRGB色域内にとどまることの保証
    • アルファチャンネルをサポートする唯一の色空間であること
  2. oklch の色が画面の色域を超えるとき、ブラウザは何をしますか?
    • 宣言を無視し、直前の色を保持する
    • 主にクロマを減らす色域マッピングを適用する
    • それ以上の処理をせず、各RGBチャンネルを独立にクリップする
  3. clamp(MIN, VAL, MAX) において、計算されたMINの値がMAXを超えたらどうなりますか?
    • 宣言が無効になり、無視される
    • MAXが勝ち、結果を上限で抑える
    • MINが勝つ。clamp は max(MIN, min(VAL, MAX)) に展開されるから