CSSのfilterを使って、背景色に合わせた文字色を自動的に設定する

背景色が動的に変わる状況で、文字色を良い感じに設定したい事があります。 ユーザーの入力によって色が決まるとか、外部のAPIが色を決めてるとか。

このサイトのworksページの各リポジトリについている、「Python」とか「TypeScript」とかの言語タグの色がそんな感じになっています。 この色はGitHubのAPIが決めているものなのですが、文字色の方は提供してくれないのでCSSで動的に計算するようにしています。

ここで使っているテクニックが地味に面白いのでご紹介します。

やり方

色設定のコードは以下のような感じ。

<div>
    <span>hello world!</span>
</div>

<style>
div {
    background-color: red;
}
span {
    color: red;
    filter: invert(100%) grayscale(100%) contrast(100);
}
</style>

以上、これだけ。 背景色と同じ色を文字色にも設定しちゃって、CSSのfilterを使って見える色に変化させています。

実際色んな色でやってみると以下のような表示になります。

#000000
#000080
#0000FF
#008000
#008080
#0080FF
#00FF00
#00FF80
#00FFFF
#800000
#800080
#8000FF
#808000
#808080
#8080FF
#80FF00
#80FF80
#80FFFF
#FF0000
#FF0080
#FF00FF
#FF8000
#FF8080
#FF80FF
#FFFF00
#FFFF80
#FFFFFF

基本全部に上手いこと色を当ててくれている感じ。

ただ、中間付近の色(#8080FFとか)だとちょっと微妙ですね。 あとはinvert()が効かない完全な中間色である#808080などはかなり見辛くなります。

とはいえ、この簡単さで基本上手くいっているので十分でしょう。

ブラウザの対応状況

基本的なブラウザで使用することが出来ますが、IEだけは対応しないのでご注意。

まあもうIEは良いでしょう。良いということにしましょう。

Can I useで調べたCSS Filter Effectsの対応状況。主要ブラウザだとIE11だけが非対応。

仕組み

まずは同じ色で描画する

最初はfilterを掛ける前の状態から。

背景と色を同じ色で描画します。 同じ色なので当然ですが、そのままでは全く見えません。

#FFCCCC
#FF8E8E
#FF0000
#8E0000
#330000

invertで色を反転させる

この状態から文字色だけにinvert(100%)を当てることで色を反転させて、ちゃんと目に見えるようにします。

#FFCCCC
#FF8E8E
#FF0000
#8E0000
#330000

モノクロにして見やすくする

色を反転させただけだと反対色な上にコントラストが凄いことになるので、彩度が高いと目が痛い感じになります。

なので、grayscale(100%)を設定してモノクロにしてあげます。

#FFCCCC
#FF8E8E
#FF0000
#8E0000
#330000

コントラストを上げて更に見やすくする

モノクロ化することで目が痛いことはなくなりましたが、今度はコントラストが低すぎて見えづらいです。

というわけで、contrast(100)でコントラストをがっつり上げて白か黒かに固定します。

#FFCCCC
#FF8E8E
#FF0000
#8E0000
#330000

これで完成。結構シンプルです。