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

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

そこで、文字色が動的に設定される方法を考えてみました。それも、CSSだけで。
実際に動かしてみると以下のような表示になります。

#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

いかがでしょうか。 グレー(#808080)に近い色はやや見づらくなってしまっていますが、それ以外はかなり上手く表示できているのではないかと思います。

やり方

上記のサンプルは以下のようなCSSで実現しています。

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

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

以上、これだけです。

詳しい解説は後述しますが、colorbackground-colorに同じ色を設定してから、文字色だけCSSのfilterで見える色に変化させる仕組みです。

なお、divとspanをセットにすると背景色にもフィルターが適用されてしまうので注意してください。

ブラウザの対応状況

今回使用したCSS Filterは基本的なブラウザで使用することが出来ます。

ただ、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

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


Q&A:

  • CSSの機能だけで背景色に合わせた文字色を選ばせるには?
    → filterを使って、invert(100%)で反転した色をgrayscale(100%) contrast(100)で白黒にして使ってあげればそれらしくなります。

  • CSSだけで文字や画像の色を反転させるには?
    invert(100%)というフィルタが使えます。

  • CSSで文字や画像を白黒にするには?
    grayscale(100%)というフィルタでグレースケールにしたあと、contrast(100)でコントラストを上げれば白黒になります。


参考: filter - CSS: カスケーディングスタイルシート | MDN

2024-01-25 追記

読みやすさのために一部構成を変更しました。