Appleデバイスでtransparentのグラデーションが黒くなる現象

初めまして。去年にネコメシにジョインしたシライシです。

html, cssをメインに時々jsを書くお仕事をしております。今後ともよろしくお願いいたします。

Tl;Dr

  • Appleデバイスでtransparentのグラデーションが黒い
  • transparentは黒
  • グラデーションの計算は乗算済みアルファ
  • 解決策は色指定を明示的にすること

グラデーションが黒っぽくなる

さて、本題です。タイトルの通りの現象が起こりました。

MacやiOSのSafariで transparent からのグラデーションが黒くなる現象に遭遇しました。

コードで言うと、

background: linear-gradient(to right, transparent, #f00)

のような指定の仕方です。

期待する動作は透明から赤へのグラデーションです。実際にChrome, Firefox, IE, Edgeのブラウザだと期待通りの動作なのですが、Safariだけ異なる表示となります。

実物をご覧ください。ChromeとSafariで見比べていただけるとわかるかと思います。

https://jsfiddle.net/zufb7tks/1/

キャプチャ画像

transparentは黒

なぜSafariだけこのような動作になるかを調査してみました。

まずは transparent とはなんぞやを調べてみました。

W3Cの仕様書だと transparentrgba(0, 0, 0, 0) のショートハンドと定義さております。

W3Cのtransparentの仕様書

https://www.w3.org/TR/css-color-3/#transparent

transparent は黒だったのです。

普段、透明にすると言う意図で使ってましたが、rgba(0, 0, 0, 0) のショートハンドとは知らなかったです。

つまり、先ほどのコードは background: linear-gradient(to right, rgba(0, 0, 0, 0), #f00)と同じとなります。

黒からのグラデなら黒っぽくなるのは当たり前か、とも思ったのですが、それでは他のブラウザが透明からの動作になっていることがわかりません。

グラデーションの計算は乗算済みアルファ

次にグラデーションの仕様を調べてみることにしました。

これまた答えはW3Cの仕様書にありました。

グラデーションは乗算済みアルファ(よくわからん)で計算するように定義されておりました。

W3Cのグラデーションの仕様書
https://www.w3.org/TR/css-images-3/#coloring-gradient-line

さらにMDNドキュメントによると

古いブラウザーはアルファ―チャンネルが 0 の値である黒として扱うかもしれません。

https://developer.mozilla.org/ja/docs/Web/CSS/color_value#transparent

という記述も発見できました。古いブラウザではグラデーションの計算方法が異なるようです。

ここから推察するにSafariは古い仕様に則っているため、黒からのグラデーションとして計算され、その他のChromeなどのブラウザではアルファ乗算で計算されたグラデーションがレンダリングされて、期待通りの動作となっていることがわかります。

なるほどなるほど。納得できそうな答えにたどり着けました。

アルファ乗算のような画像処理には明るくないため、わかりやすい記事を発見いたしましたので、そちらのリンクを貼っておきます。何かの参考になればと思います。

乗算済みアルファとは?
https://blogs.msdn.microsoft.com/ito/2010/07/10/423/

解決策は色指定を明示的にすること

仕様を調べてたりしましたが、対処方法は至ってシンプルで、transparent を使わず 望みの色のアルファチャンネル 0 の値を設定することです。

background: linear-gradient(to right, rgba(255, 0, 0, 0), rgba(255, 0, 0, 1));

こうすることでメジャーなブラウザで期待通りの色となります。

デザインツールからcssをコピーする方法をとってる人だとあまり出くわさないケースだったかも知れませんね。