てもとツール
ガイド

CSSグラデーションの真ん中がくすむ原因|灰色を避ける2つの直し方

カラーコードで書いたCSSグラデーションは、赤・緑・青の数値をそのまま混ぜるので、青と黄のような反対の色どうしだと真ん中がちょうど灰色の#808080になります。真ん中に色を1つ足す方法と、in oklchで混ぜ方を変える方法を、Chromeで測った色の値で比べました。

公開読了目安 約5分

この記事の要点

  • カラーコードで書いたグラデーションは、赤・緑・青の数値をそのまま割合で混ぜて途中の色を作る
  • 青(#0000FF)と黄(#FFFF00)なら、真ん中はちょうど灰色の#808080になる
  • 色相が近い2色なら、同じ混ぜ方でもくすみはほとんど目立たない
  • 真ん中に鮮やかな色を1つ足す直し方は、混ぜ方を変えられない古いブラウザでも効く
  • in oklchで混ぜ方を変えると真ん中も鮮やかになるが、両端に無い色が途中に出る
目次

CSSのグラデーションの真ん中がくすむのは、カラーコードで書いた色を、赤・緑・青の数値のまま混ぜているからです。 青と黄のように数値がちょうど逆の2色では、真ん中が灰色の#808080になります。

直し方は2つあります。 真ん中に鮮やかな色を1つ足すか、in oklch のように混ぜ方を指定するかです。

この記事では、くすむ仕組みと2つの直し方を、Chromeで測った色の値で比べます。

真ん中がくすむのは、色の数値をそのまま平均するから

カラーコードの#0000FFは、赤・緑・青の量を0〜255の3つの数で表しています。 グラデーションの途中の色は、両端の3つの数を、位置の割合で混ぜて作ります。

CSSの仕様では、カラーコードやrgb()で書いた色どうしは、この数値のまま混ぜると決められています。 昔からある書き方の見た目を変えないためです。

青から黄へのグラデーションを、Chromeで5か所測りました。

位置色(赤, 緑, 青)
左端0, 0, 255
4分の164, 64, 191
真ん中128, 128, 128
4分の3191, 191, 64
右端255, 255, 0

青は「0, 0, 255」、黄は「255, 255, 0」で、3つの数がちょうど逆です。 半分ずつ混ぜると3つとも128にそろい、赤・緑・青が同じ量の灰色になります。

くすみが目立つ組み合わせ・目立たない組み合わせ

どの2色でも灰色になるわけではありません。 左から右へ混ぜたときの真ん中の色を、3つの組み合わせで測りました。 赤は#FF0000、緑は#00FF00、青→紫は#2E86C1→#8E44AD です。

両端の色真ん中見え方
青→黄#808080灰色
赤→緑#808000暗い黄土色
青→紫#5E65B7青紫

3つの数がちょうど逆の2色なら、半分ずつ足すと3つとも127.5になり、真ん中は必ず灰色になります。 赤(#FF0000)と水色(#00FFFF)も、真ん中は同じ#808080でした。

赤→緑は灰色にはなりませんが、真ん中が両端のどちらよりも暗く見えます。 明るさの差をそろえて測る指標(OKLabの明るさ)では、赤が0.63・緑が0.87に対し、真ん中は0.58でした。 CSSの色名の green は#008000で、ここで使った#00FF00とは別の色です。

青(#2E86C1)→紫(#8E44AD)のように色相が近い2色では、真ん中もはっきりした青紫です。 次の節の in oklab で混ぜても、真ん中は#6F69B7で、赤が17・緑が4違うだけでした。

直し方1:真ん中に色を1つ足す

いちばん確実なのは、くすむ位置に自分で色を置くことです。 青と黄のあいだなら、緑がかった水色(#00C896)を真ん中に足します。

background: linear-gradient(
  to right,
  #0000FF 0%,
  #00C896 50%,
  #FFFF00 100%
);

Chromeで測ると、4分の1は「0, 100, 203」、4分の3は「128, 228, 75」で、どこも灰色になりませんでした。 足す色は、両端の色相のあいだにある鮮やかな色から選びます。

この方法は、混ぜ方の指定に対応していない古いブラウザでも、同じ見た目になります。 CSSグラデーション生成なら、「+ 色を追加」で8色まで置けるので、プレビューを見ながら真ん中の色を選べます。

直し方2:混ぜ方を in oklch や in oklab に変える

グラデーションの向きのあとに in oklch と書くと、色の混ぜ方そのものを変えられます。

background: linear-gradient(
  to right in oklch,
  #0000FF,
  #FFFF00
);

青→黄の真ん中の色は、指定によって次のように変わりました。

指定真ん中見え方
なし#808080灰色
in oklab#6CACC7くすんだ水色
in oklch#00CFBD鮮やかな青緑

oklabは、人の目で感じる色の差がなるべく均等になるように作られた色の表し方です。 真ん中が暗く沈むことは避けられますが、反対の色どうしでは灰色寄りの色が残ります。

oklchは、色相をぐるりと回って混ぜます。 そのため、青→黄の途中に、両端のどちらにも無い水色や緑が出てきます。

計算の上では、真ん中の鮮やかさは両端の値のあいだに保たれます。 ただし画面で出せない色は出せる範囲に寄せて描かれるので、測った真ん中の鮮やかさは両端より低くなりました。 それでも、OKLChの彩度で比べるとoklabの真ん中の約1.8倍です。

CSSグラデーション生成が書き出すコードには in の指定が入らないので、使うときはコードに書き足します。

透明に向かうグラデーションが灰色がかるとき

transparent は「透明な黒」を表す色です。 古いブラウザでは、赤から透明へのグラデーションの途中に、黒が混ざって灰色がかることがありました。

いまのブラウザは、色を透明度で掛けてから混ぜるので、この灰色は出ません。 Chromeで測ると、透明→赤の真ん中は、白い背景の上で「255, 128, 128」の明るい赤でした。

MDNの互換表では、この混ぜ方はSafariでは15から使われています。 それより前のSafariも気にするなら、transparent の代わりに同じ色の透明版を書きます。 赤なら rgba(255, 0, 0, 0) です。

関連記事

参考・出典

本記事は上記の公的機関・公式情報源を参考にしています。最新の情報は各リンク先をご確認ください。

あわせて読みたい

同じテーマ・関連ツールの記事です。