color-mix() vs opacity — どちらをいつ使うか
色を transparent 寄りに混ぜるのと、opacity プロパティを使うのとの実際の違いを理解します。アクセシビリティとスタッキングへの影響も含みます。
Advanced
詳細な説明
色を「フェード」させる 2 つの方法と、その違い
opacity: 0.5 と color-mix(in oklch, c, transparent 50%) は同じ
ことをすると思いがちです。違います。
opacity: 0.5
.card { background: blue; opacity: 0.5; }
これは 要素全体 をフェードさせます — テキスト、アイコン、ボーダー、 子コンポーネントすべて。新しいスタッキングコンテキストも作ります。 「ゴースト」オーバーレイには有用ですが、アクセシビリティには破滅的: 内部のテキストは元の色選択が問題なくても、コントラストチェックに 失敗します。
color-mix(... transparent 50%)
.card { background: color-mix(in oklch, blue, transparent 50%); }
これは 背景だけ をフェードします。中のテキストとアイコンは 完全な不透明度を保ちます。スタッキングコンテキストの罠もありません。
実用的な決定木
| 目的 | 使うもの |
|---|---|
| 遷移中にポップオーバー全体をフェード | opacity |
| 半透明ヘッダー背景を表示 | color-mix(... transparent ...) |
| ボタングループ全体の無効状態 | opacity |
| 無効状態の背景塗りだがラベルは読みやすく | color-mix(... transparent ...) |
| 50% チップ背景ティント | color-mix(... transparent ...) |
おまけ: Relative Color Syntax によるアルファ演算
既存の色のアルファを正確に半分にしたい場合、 Relative Color Syntax が直接アクセスを提供します:
.faded { color: oklch(from var(--brand) l c h / calc(alpha * 0.5)); }
ユースケース
視覚的フェードに `opacity` を使ってアクセシビリティ退行を起こしている既存コードのリファクタリング。半透明 UI サーフェスに適切なプリミティブを選ぶ場面。