CSS グラデーションが「のっぺり」する原因と、デザイナーが嫌がらない作り方
執筆: ありがっさまりょうた
デジタル道具屋を個人で開発・運用しています。記事は実装時の検証結果と公式仕様を照合して執筆しています。
本記事の執筆方針と編集ポリシーについてはAbout ページをご覧ください。
指定どおりの色なのにグラデーションが濁って見える理由
デザインカンプで指定された HEX コードをそのまま linear-gradient() に渡したのに、 中間部分が濁って見える、というケースは珍しくありません。 原因の多くは、色の指定ミスではなく「2色の間をどの色空間で補間しているか」にあります。
例えば linear-gradient(blue, yellow) は、既定の sRGB 空間で補間されます。blue は rgb(0 0 255)、yellow は rgb(255 255 0) なので、 ちょうど中間の点は各チャンネルの平均である rgb(128 128 128)、つまり純粋な灰色になります。 両端はどちらも鮮やかな色なのに、中央だけ彩度がゼロに落ちる、というのが「泥のような灰色」の正体です。
この問題は、青と黄のように色相が遠い(補色に近い)2色を直接つないだときに顕著になります。 解決策は大きく2つで、中間色を1つ挟むか、色相環を経由する色空間(HSL や OKLCH)で補間するかです。以下で順に説明します。
1. グラデーションが「のっぺり/濁る」3大原因
グラデーションが濁る、あるいは平板に見える典型的な原因は、次の3つに集約されます。
- 補間色空間が sRGB のまま:色相が遠い2色(補色関係)を直接つなぐと、中間がグレーに沈む
- 中間カラーストップが無い:2色だけで距離が長いと、変化が直線的すぎて「帯」に見える
- 色の明度差が大きすぎる:白〜濃紺など極端な明度ジャンプは、画面サイズによってはバンディング(縞)の原因になる
これらは互いに独立した要因なので、1つだけ対処しても改善しないことがあります。 濁りが取れないときは、3つすべてに該当していないかを順に確認してください。
2. 補間色空間を意識するだけで化ける
CSS Color Module Level 4 から、グラデーションの補間色空間を in oklch や in hsl のように指定できるようになりました。 色相環を経由する補間に切り替えると、彩度を保ったまま自然に変化します。
濁る書き方
background: linear-gradient(90deg, #2196f3, #ffeb3b);
/* 中間が灰色っぽくなりがち */OKLCH 補間
background: linear-gradient(in oklch 90deg, #2196f3, #ffeb3b);
/* 色相環を経由するため、彩度を保ったまま遷移 */上の「濁る書き方」の中間点を実際に計算すると、#2196f3(rgb(33 150 243))と#ffeb3b(rgb(255 235 59))の各チャンネル平均は rgb(144 193 151) になります。 HSL に換算すると彩度はおよそ 28% で、両端(およそ 90〜100%)に比べて大きく落ち込んでいます。 これが「灰緑色の帯」として見える部分です。
OKLCH は人間の知覚に近い色空間で、明度(L)を一定に保ったまま色相(H)だけを動かせます。 グラデーションだけでなく、デザインシステムのアクセントカラーの派生色を作る際にも同じ性質が役立ちます。 なお in hsl や in oklch の色相補間は、既定では色相環の短い側(shorter hue)を通ります。 あえて長い側を通したい場合は in oklch longer hue のように指定します。
古いブラウザを考慮するなら「中間ストップ」
in oklch はモダンブラウザでは動きますが、レガシー対応が必要な場合は中間カラーストップを明示的に挟むのが確実です。 例えば青→黄なら、間に「青寄りの紫」「ピンク」など、色相環を時計回りに辿る色を 1〜2 個挟むだけで、濁りは消えます。 逆回りに、シアン〜緑を経由させても構いません。要点は「中間点が無彩色にならない色を明示する」ことです。
中間ストップで濁りを回避(sRGB 補間のまま動く)
/* 中間にティール(#26c6a3)を置く。青(色相 約207°)→ティール(約161°)→黄(約54°) と
色相環の短い側を経由するので、どの区間も無彩色を通らない */
background: linear-gradient(90deg, #2196f3, #26c6a3 50%, #ffeb3b);3. 線形 / 放射状 / 円錐の使い分け
CSS のグラデーション関数は大きく3種類あり、デザインの意図によって使い分けます。
| 関数 | 用途 | 注意点 |
|---|---|---|
linear-gradient | 背景の方向感、シンプルなボタンの陰影 | 角度を 90deg や to right で明示 |
radial-gradient | スポットライト効果、中心への注目誘導 | circle at top right など中心位置を指定 |
conic-gradient | ドーナツチャート、虹色グラデ、装飾的な背景 | 境目が鋭くなりがち。色の手前に 0deg, X 50% で繰り返し |
conic-gradient は角度に沿って色が変わるため、同じ位置に2つのストップを置くと境界がくっきり分かれます。 この性質を使うと、画像や Canvas を使わずに CSS だけでドーナツチャートを作れます。
4. よくある失敗パターンと対策
パターン1:iOS Safari で線が見える(バンディング)
グラデーションが帯状の縞として見える現象です。8bit カラーでは1チャンネルあたり 256 段階しか表現できないため、 明度差の小さい範囲を広い面積で引き伸ばすと、隣り合う段階の差が目に見えてしまいます。 対策は SVG の feTurbulence フィルタで作ったノイズを薄く重ねるか、半透明の ::after でディザを入れることです。 極端な明度差を縮める(白→灰白など)でも軽減できます。
パターン2:ボタンのグラデが「ペカペカ」して安っぽい
色差が大きすぎる、もしくは中央がハイライトになっていないケースが多いです。 定番の手法は、linear-gradient(180deg, rgba(255,255,255,0.15), rgba(0,0,0,0.05)) を主色の上に重ねて、 立体感だけを軽く付与することです。色そのものは単色のまま変えません。
パターン3:グラデ背景上の文字が読めない
テキストとの間に background-blend-mode: multiply や半透明オーバーレイを挟むのが定石です。 WCAG AA 基準(コントラスト比 4.5:1 以上)は、最も明るい点と最も暗い点の両方で確認します。 ヒーローセクションでは「下半分だけグラデを濃くする」テクニックも有効です。
注意点:CSS変数とグラデーションの併用
--accent: #ff0000 のような CSS変数をグラデーションに使う場合、ブラウザによっては再描画コストが高くなります。 アニメーション(カーソル追従など)でグラデを動かすときは、@property で型を明示するか、 要素自体を transform で動かす方が滑らかです。
5. ジェネレーターで叩き台を作ってから調整する
ゼロから書くと、角度・色・カラーストップの調整に時間がかかりがちです。 当サイトのCSSグラデーション作成ツールでは、 ビジュアルで色とカラーストップを調整しながら、即座に CSS コードをコピーできます。 生成したコードをベースに、本記事の OKLCH 補間や中間ストップのテクニックを追加して仕上げると、 調整の手戻りを減らせます。
関連: Box Shadow 作成、Border Radius 作成 も組み合わせると、UI パーツの試作が一気に進みます。
参考にした一次情報
本記事の内容は、以下の公式仕様や一次情報を参照して執筆しています。
- CSS Images Module Level 4 - Gradients
W3C
https://www.w3.org/TR/css-images-4/#gradients
- linear-gradient() - CSS: Cascading Style Sheets | MDN
MDN Web Docs
https://developer.mozilla.org/ja/docs/Web/CSS/gradient/linear-gradient
- CSS Color Module Level 4 - Color Interpolation
W3C
https://www.w3.org/TR/css-color-4/#interpolation
この記事の内容を実際に試す
解説した内容は、以下のツールでブラウザ上から無料で試せます。