CSSでブラウザがコントラスト色を自動選択!驚きの方法とは?
引用元:https://news.ycombinator.com/item?id=44015367
この記事の問題について、inclusivecolors.comっていうツールを作ってるよ。色のペアがWCAG/ACPAコントラストになるパレットを作る手助けをするんだ(デスクトップ版はもっと機能がある)。一つのやり方として、明るさ別に100から900までの色のスウォッチを作るの。特定の明るさの組み合わせで、例えば700番が100番と必ずコントラストがつくように設計できるんだ。
そうすれば、いちいちチェックしなくてもコントラストがつく組み合わせがわかる。
Contrastメニューでは、APCAアルゴリズムがWCAGよりどれだけ厳密か調べられるよ。特にダークテーマではAPCAを使うべき。TailwindとかIBM Carbonみたいなパレットは、明るさ以外の要素も複雑に調整してるから、単純な白黒自動選択よりは奥深い話だね。
LCHを使って、これに近いことやる方法があるよ: –text: lch(from var(–bg) calc((49.44 - l) * infinity) 0 0);
ソースはここ: https://til.jakelazaroff.com/css/swap-between-black-and-whit…
LCHもすごいけど、OKLCHはもっとすごいんだ!
https://evilmartians.com/chronicles/oklch-in-css-why-quit-rg…
正直、この記事でこの件に関する考え方が劇的に変わったよ、本当に素晴らしいツールだ。デザイナーの友達がoklchのこと全然知らなかったのにすごく驚いたんだけど、これ、色々な問題を解決してくれるんだ。
こんなコールバックみたいなスタイルで、パラメータを変更できるCSS関数見たことないな。超面白い!他にこういう例はあるの?それともこれはlchだけ?
これは”relative color”シンタックスっていうんだよ、色々なカラースペースやカラー関数で使える。鍵となるのは先頭の”from”だね。MDNドキュメントはここにあるよ: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/…
紛らわしいかもしれないけど、ここの全部は静的なパラメータだよ。—-接頭辞はCSS変数で、CSS宣言ブロック内で—-bg: blueって書くやつね。
”l”は違うよ!
calc-sizeみたいな新しいやつもこんな感じだよ。
lea verouから、こんな感じの回避策についての良い記事があるよ https://lea.verou.me/blog/2024/contrast-color/
これ、良い点と悪い点すごく分かりやすいね。シンプルなサイトならこれで十分コントラストしっかりさせられるし楽ちん。でも、WCAG対応が必要なプロダクション規模なら、Semantic tokens使った方がいいよ。Semantic tokensは開発早くなるし、黒か白に変えるより見た目もちゃんとコントラスト保てる。テーマ化も超簡単だから、ライトモードとかダークモードもほぼ手間なし。ブランド色がWCAG2で問題あっても、WCAG2とかAPCA対応のテーマも作れるから、コンプライアンス守りつつもっと良い見た目のコントラストも提供できるんだ。これ、僕の専門分野でね、Figmaで変数とかトークン担当してるし、FigmaとかAtlassianでダークモード実装してたんだ。トークンとかテーマとか、アクセシブルな色について質問あったら何でも聞いてね。
Semantic tokensってどういう意味?まさにこういう機能(自動コントラスト)のせいで、仕事の大きなプロジェクトでCSS in JS使わざるを得なかったんだよね(相対色とかコントラスト色のために)。こういうのが一般的に使えるようになるの嬉しいな、数年後が楽しみ。
Webの色に関して言うと、Semantic tokensっていうのはCSS変数で、bg-brandみたいに使い道で名前をつけたものだよ(ブランドカラーを背景に使う時とか)。だいたい3つの”階層”があるんだ:primitive、semantic、component。Primitiveトークンは値そのもの、例えば色のグラデーション(赤/100とか)。Semanticトークンはprimitiveトークンを参照する。bg-brandが青/300になってたりね。Component層はコンポーネントのどこで使うか(ボタンの背景とかボタンのテキスト)。でもcomponent層はよっぽどのマルチブランド状況じゃない限り、”絶対絶対”オススメしないよ。Unileverみたいな会社じゃないなら、componentトークンは使うべきじゃない。
Design systemでのトークン命名規則ってたくさんあるんじゃないの?これを一般的なプラクティスみたいに言うのはちょっと言い過ぎじゃない?(記事リンク)
Nathanは僕が言った各階層内の命名規則の話をしてるんだよ、階層そのものの話じゃなくてね。あのブログはsemantic層とかcomponent層の命名規則について詳説してる。primitive/semantic/componentっていう階層セットは一般的なプラクティスだよ。中での命名は目的によって大きく違うし、それで良いんだ。使う個別のトークンの名前は、目標とか意図で決まるんだよ。例えばGoogleのMaterialのsemantic層は、カラフルな多様なテーマ向けに設計された命名スキーマを使ってるけど(使い方の分かりやすさとのトレードオフで)、Appleはアプリのデザインがあまりデザインの違いがないから、もっとシンプルなのを使ってるんだ。
親コメントじゃないけど、その一般化は正しいよ。普通はベース層(red/300とか)と、もっと意味的なsemantic層(.text-dangerとか)がある。リンク先にもあるように、その上にどんなテーマとかシステムを実装するかで、何百万通りもの実装方法があるんだよね。
これはユーザーにサイトのテーマを選ばせない場合にしか使えないね。もし選ばせるなら、記事のやり方の方がうまくいくと思うよ。
同意するんだけど、後半の2/3はなんか意味不明な専門用語の羅列に聞こえるだけだな、自分を賢く見せようとしてるみたい。真実じゃないとは言わないけど、単なる言葉の羅列だね。この機能(自動コントラスト)は好きなんだけど、企業サイトやアプリケーションでこれに頼るのはやめた方がいいな。結果をコントロールできないから。WebKitが後でバグを修正したり何か変更したりして、結果の色が自分が意図しないものに変わるかもしれない。それが怖いんだ。
>でも、大きなプロジェクトで、大勢のチームで、そういう細かいところを丁寧に管理するのは、ちゃんとやるのが本当に大変になる可能性がある。突然暗いボタンのテキストが読めない黒になって、ユーザーが何をすればいいか分からなくなる、とかね。
大きなプロジェクトが出荷される前に、誰かボタンを見られないのかな?代わりに、暗いボタンに黒いテキストを使うのを強制的に禁止して、大勢のメンバーも含めて全員に伝えるとか。知覚コントラストと数学的コントラストの話は面白いね、知らなかったよ。自分の仕事のやり方に取り入れてみよう。
「大きなプロジェクト出荷前にボタン確認できないの?」ってさ、そりゃできるけど、そうするとリグレッションテストが何週間もかかるんだよね。”大きなプロジェクト”だとボタン何千個とか普通にあるし、特定の設定や複雑な操作でしか見えないのもいっぱいあるからね。
APCAについて読んでみるといいかも。APCAアルゴリズムを使えば、知覚的なコントラスト計算ができるよ。
WCAG2でもできるよ。記事のよくあるAPCAの例は大事なとこ隠してるし、多くの間違った結論につながってるな(つまり:どの基準でも黒の方がコントラスト高いんだけど、APCAはそんなにコントラスト要らないって言うから、白でも十分なコントラストになるってだけ)。
WCAGも知ってるけど、もっとシンプルに色を暗いか判定する関数を作るだけでもいけるよ。例えば輝度を計算して0.5みたいな閾値と比べる方法とかね。WCAGの輝度計算式とか使う感じ。>APCAはそんなにコントラストいらないって言う
でも、APCAでも目標コントラスト値はいつでも調整できるから大丈夫。簡単な方法はいっぱいあるよ。
WCAGの輝度式(色科学でいう相対輝度)だと知覚的な中間グレーは0.5じゃなく0.18だよ。APCAの目標コントラストを変えるって話は記事の間違いとは別。APCAが「コントラストそんなにいらない」って言うのはいいんだけど、記事が「白の方がコントラスト高い」って結論づけてるのが間違いってことね。
そうだね、0.5は0-1の中間点で分かりやすい例だったけど、知覚的には0.18の方が”中間グレー”に近いのは君の言う通り。目が暗い色に敏感だからね。色が明るく感じるか暗く感じるか判断するなら0.18に近い閾値の方がいいかも。でも0.5は数学的な中間点としては合ってるし、人間の知覚とも合うよ(追記)。結局0.18〜0.3を閾値にすることもできるね。
>0-1の輝度範囲の中間点
輝度には相対輝度と知覚輝度があるんだ。君が言ってた輝度計算(相対輝度)で0.5を使うと間違い(細かいけどa11y重要!知覚輝度なら0.5はWCAG2にぴったり)。>人間の知覚と合わない
人間の知覚と100%合ってるよ。古い成果物だ。>結局0.18〜0.3を閾値として使える
知覚輝度と相対輝度には定義がある。背景色CでコントラストKが必要なら可変じゃない。KとCで出力範囲があるって意味では君の言うことも価値あるけどね。例えば必要なコントラストが+40 LでCが50 Lなら、使える色は90-100 Lと0-10 Lだよ。
え、じゃあ結局0.5で合ってたの?!0.5は完全に間違ってるし人間の知覚と合わないと思ってたのは、自分が間違ってると思ってたからか。イタタ。まあ、しばらくやってなかったからね :D
そういえば、このシンプルな方法で色が暗いか判定できるかな?
$luminance = 0.299 * $r + 0.587 * $g + 0.114 * $b;
return $luminance < $threshold;
閾値は128だったっけ?この場合は128がよくある閾値だった気がするんだけど。
昔、0.3R + 0.6G + 0.1B < 128ってやり方でやったことあるよ。深く考えるのが面倒だったからね。完璧じゃなかったのは確かで、コントラストのために黒か白か逆の方が良かった明らかなケースもあったけど、自分の目的(背景色に関係なくラベルが少なくとも読めるようにする)には十分うまくいったよ。
俺はコントラストがすごく重要なのを実装したから、もっと高度なアルゴリズム使ってるよ。でもまあ、そこまで凝らなくてもいける場合もあるよね :D
”black has more contrast by either measure”っていうけど、違うんじゃないの?ブログ記事の計算機のスクショ見たら、APCAだと白の方が明らかにコントラスト高いって出てるじゃん。(マイナスの数値がややこしいなら、BridgePCA計算機みたいなのでWCAG 2の”contrast ratio”っぽいメトリクスをAPCAで計算してみるといいよ。)APCAの目的はコントラスト計算を知覚的にもっと正確にすることで、単に閾値を下げることじゃないから。
APCAが閾値を下げるのは正確さを追求した副作用だよ。非知覚的なコントラストなんてないし。あと、BCPAの計算がおかしいのは、記事で使われてる36ptじゃなくて12ptで計算してるからだよ。だからコントラスト比がおかしく表示されちゃってるんだ。
もっとコメントを表示(1)
白い方がシャープに見えるかと思ったけど、そうでもないみたい。青の色をちょっと濃くした方がしっくりくるな。
ブラウザがコントラストの色を決めるってどうなんだろう?いつも正しく予測できるわけじゃないだろうし、全ブラウザで同じ基準になるのかな?デザインチームが使うツールとしてなら良さそうだけどね。
記事に書いてあったけど、標準で計算方法が決まってるみたいだよ。
HDRディスプレイとか組み込みデバイスとか、特殊な環境だと問題が出ないか心配だなあ。標準的なSafariとかChromeなら多分大丈夫だろうけど。間違ってたら嬉しいけどね。
「選択する」っていう言葉は変だね。色を計算してるんだから、「計算する」の方が正しいんじゃない?
news.ycombinator.comのスレッドも見てみて。APCAのボタンの例で混乱してる部分を除けば、あれは100%正しいって。背景の色が明るいか暗いか(L*値が60以上かどうか)で、白か黒どっちを使うか決めれば、もっと正確で一貫性のある結果になるよ。
昔システムカラーでスタイル作ってたんだけど、色の組み合わせ(buttonFaceとかbuttonTextとか)が全然コントラスト足りなくて意味なかったんだよね。JSでコントラスト計算して、ダメなら他の色にしたり、text-shadowで文字の周りを暗くしたり明るくしたりしてたよ。RGBの平均で計算できないかな?
最低でもactiveとかfocus、hoverとかlink、visitedみたいな疑似クラスとか、ライト/ダークテーマの組み合わせで良い色がわかると嬉しいな。Material UIだとdisabledとかbefore、afterもあるし。
昔、これと似た動画チュートリアル作ったんだ〜。背景色に合わせてテキスト色を黒か白か選ぶやつね。すごく簡単な方法で、色をグレースケールにして黒と白を比べただけ。面白いプロジェクトだったけど、動画作るの苦手なんだ。動画はポルトガル語だから気をつけてね。
https://youtu.be/tUJvE4xfTgo?si=vFlegFA_7lzijfSR
面白いね!別のコメントでまさにそれをするカラー空間の数式が出てたよ。
https://news.ycombinator.com/item?id=44015990
動画は良さそうに見えるね。ポルトガル語話せないから何言ってるか分からないけど、コードは良さそうだよ!
カラーテーマの色は自分で選ぶのに、最初からコントラストのある色を選べばいいじゃん?これがなんで簡単なの?個人の自由な背景色とコントラスト不足の前景色を同時に許す、ダメなチーム向けなの?本当に必要なのは画像上のテキストとか、常にちゃんと見えることだよ。これは全然役に立たないじゃん。
だから、これは怪しい状況でしか使えないのに、新しい言葉まで作って、機能は貧弱(黒か白だけ)、しかもアルゴリズムが最悪(知覚的コントラスト無視)。すごいね!
使ったことないってだけでツールをすぐダメって言うのは良くないよ。多くのサイトでユーザーが色を選んだり、自動で決めたりできるじゃん[1]。アクセシビリティ考えるなら、コントラストカラーを計算するのが普通。このツールは多くのサイトが基本的なアクセシビリティを用意するのに役立つし、良い体験を作りたい人の邪魔にならない。
npmのcontrast-colorみたいにカスタマイズできたら最高だけど、ブログ記事にはなんで白/黒から始めて後でアルゴリズムを変えるか書いてあるよ。
[1] 例:https://coolors.co/8fbfe0-7c77b9-1d8a99-0bc9cd-14fff7
そうだね。簡単な使い方だと、ユーザーが”タグ”を作って、そのチップの色を自分で選べるようにしたかった時とか(GithubのPRタグの”good-first-issue”とか”bugs”みたいにカスタムできるやつ)。
親コメントがこの使い方を知らないなんてびっくりだよ、どこでも見るのに。
> and they did it with the worst possible contrast selection algorithm
彼らはちゃんとWCAG 2のアルゴリズムに従ってるって言ってるし、WCAG 3でこの問題が修正されるかもって言ってるよ。将来、標準化されたらもっと良いアルゴリズムを使うように簡単に変えられるとも言ってるし。
これをビルド時にやる良い方法ってない?SASSとかTailwindの上で動くやつとか?
この機能がみんな使えるようになるまで時間かかりそうだし、どのプラットフォームでも同じ(正しい)やり方で実装されるかちょっと心配だな。
この機能の今後の予定ね、このスレッドで出てた心配事の多くに対応してるみたいだよ:
https://drafts.csswg.org/css-color-6/#colorcontrast
最近、ブラウザを500行で作ったんだけど、色を自動で選ぶコントラスト機能も200行で追加したんだ。
その過程で色空間のこと勉強になったよ。
俺のアプローチと記事のやつはちょっと違って、これはオーサリング時のツールなんだ。
もしコントラストが足りる色が見つからなかったらエラーになるから、背景を変えないといけないんだよね。
すごいね!俺も似たようなことPythonとターミナルの色で手動でやったことあるよ。
昔、YIQ値を使って似たようなことやったの覚えてるわ。
これについてブックマークしてる方法がここにあるよ。
>このブラウザはcontrast-color()に対応してないよ。
Safari Technology Previewみたいな対応してるブラウザでこのデモ試してみてね。
Technology Previewはいらないよ、普通のSafariの詳細設定にあるWebKit Feature Flagで使えるんだ。
スマホで有効にしたらデモ見れたよ。
デスクトップ版のSafari(バージョン 18.2)のフィーチャーフラグにはないみたい。
俺のデスクトップ版Safari(バージョン 18.5)では使えるよ。
バージョン古いんじゃない?
Safariはいくつかセキュリティ修正されてるからアップデートした方がいいよ。
(略)
あと18.4は標準対応とか他の機能で結構大きなアップデートだったんだ。
情報ありがとう。
アプリとかセキュリティの自動更新はしてるんだけど、macOS全体はしてなかったんだ。
ちょっと見直してみるね。
バージョン18.5(20621.2.5.11.8)使ってるけど、ちゃんとあるよ。
caniuse.comでもまだこれに関する情報が見当たらないね。たぶんめっちゃ新しいんだと思う。
MDNにもまだないみたい。しばらくはWebKitだけっぽいね。
CSS specに追加するためのドラフトは追加されたばっかり。他のブラウザがこのドラフトについて立場を示すまで、なんでAppleはSafariに-webkit-color-contrastじゃなくてcolor-contrastとして入れたのかちょっと不思議。調べた限りでは、仕様を延期する決定(2020年までさかのぼる)しか見つからないな。
新しい機能にはもう接頭辞は使われないんだ。残ってるのは古いものだけ。
今は、ブラウザのワーキンググループがその機能の最終的な仕様を決定するまで、テストのために機能フラグの後ろに隠されてるんだ。仕様が決まれば、どのブラウザメーカーも自由に一般公開リリースに実装できるってわけ。
もっとコメントを表示(2)
めっちゃ新しいね。たぶんSafariだけに入ってて、それもまだプレビュー版だと思うよ。
「Gnome Web」で動くよ。これはだいたいWebKitのラッパーみたいなもの。
”> この機能のサポートは2021年3月にSafari Technology Preview 122で最初に出荷されたんだ。
https://webkit.org/blog/11577/release-notes-for-safari-techn…
”> CSS Color 5 color-contrast() の実験的なサポートを追加したよ。
https://trac.webkit.org/changeset/273683/webkit/
確かに相対的な色彩理論のカラーホイールがこの問題の答えだよね。「Color Wheel: The Basic Color Theory for Artists and Designers」
https://dessign.net/color-wheel-theory/
残念ながら、まだfirefoxでは動かないんだ
要するに、「このブラウザはcontrast-color()をサポートしていません。サポートしているブラウザ(例えばSafari Technology Preview)でこのデモを試してください。」ってこと。
記事の内容に間違いがあることを指摘してるよ。青地に白のコントラストが低いことや、デモの見せ方についてAPCAの文脈で詳しく解説してるんだ。APCAではL* 60辺りの背景でも白前景が許容されるけど、黒前景の方が常にコントラストは高くなるって話。デモ画像で「APCAの方が高コントラスト」と誤解されがちだけど、APCAの主張は「白前景でもアクセシブルなレベル」ってことだよ。(2020年にAPCAに基づいたカラーシステムを構築し、最新のMaterial themingを可能にした経験談)
白on青のコントラスト,明らかに低いのに記事は高いって言ってるじゃん。画面おかしいの?APCAでも白の方がコントラスト高いって記事に書いてある。君の意見は全部逆で,何言ってるか全然理解できないよ。
たぶん,前の人はWCAG 2の計算式だけを信じてるんだよ。会社ってWCAG 2のルール守るのに必死で,使いやすさよりそっち優先したりするんだ。自分の目よりWCAG 2の数値を信じる人もいるくらい。WCAG 3ではAPCAみたいな良い基準が入って,Googleとかも変なボタン作るのやめてほしいね。
投票で−3付いててビックリ。
記事全体が間違ってるって読まれたみたいだけど,一部がおかしいって言いたかったんだ。理由を詳しく話してくれていいよ。
例えばMaterial Youの色の使い方には同意できない点があるし,Google社内の開発はVP間の連携不足とかAndroidの機能不全とか結構ひどかったんだ。
投票してないけど,”君の記事は間違ってる”って意見は記事全体を無視してるよ。なんで数値だけでコントラストを判断しちゃダメなのか,記事は詳しく説明してるでしょ。GoogleがMaterialとかでいつもコントラスト問題起こしてるのは,記事で批判してる「科学」に基づいて色作ってるからだね。