CSSフィルターを使って流体を表現する(+SVGフィルター)
滑らかに結合したような表現をCSSで実装する方法です。なんて言ったらいいか分からなくて、タイトルでは「流体」と表現していますが、要は「ぷよぷよ」みたいなやつですね。英語ではこういうのを「gooey」とか言ったりするみたいです。直訳するとネバネバとかベタベタとかになるんですけどね。
この「gooey」を使ったサイトを最近良く見かけるんですけど、Javascriptでやっているんだろうなぁと漠然と思っていたんですが、色々と調べてみると、CSSのfilter
要素を使って、かなり簡単に実装できることが分かりました。個人的にはあまり使う機会がないかもしれないですけど、備忘録をかねてブログにのせておきたいと思います。
CSSだけでも実装できますが、やや実用面で不安がありまして、SVGを使うことで非常に実用的になりますので、合わせて記載しておきます。
CSSのみのgooeyエフェクト
まずはCSSだけでgooeyを表現したものになります。非常に簡単です。
HTML
<div class="container">
<ul class="gooeys">
<li class="gooey"></li>
<li class="gooey"></li>
</ul>
</div>
HTMLは2つの円(丸)を作るだけですので、リスト要素を使っていますが、入れ子にさえなっていればここはどんなタグを使っても問題ありません。
CSS
.gooeys {
position: relative;
width: 400px;
height: 400px;
margin: 0 auto;
-webkit-filter: blur(20px) contrast(30);
filter: blur(20px) contrast(30);
background: #fff;
}
.gooey {
position: absolute;
top: 0;
bottom: 0;
width: 120px;
height: 120px;
margin: auto;
background: #ff0000;
border-radius: 100%;
}
.gooey:first-child {
right: 50%;
}
.gooey:nth-child(2) {
left: 50%;
}
必要なのは、親要素に対してのfilter
要素とbackground
要素だけです。あとは位置や大きさ、形、色等の指定になりますので、実質この2つの要素があれば、以下のデモのように表示させることができます。
デモ
See the Pen CSS filter gooey effect by ta$uya_42EG4M1 (@42EG4M1) on CodePen.
※上記のデモには、マウスホバーをするとアニメーションするエフェクトが追加されています。Chrome、Firefox(ともに最新版)以外のブラウザでは、正常に表示されない場合があります。
背景に画像を設定していますが、ul
要素に設定したbackground:#fff;
が効いてしまい、画像の一部が隠れてしまっています。
SVGフィルターを利用したgooeyエフェクト
上記のように、CSSだけでも十分それっぽく表現することはできるのですが、直近の親要素に必ず一色で背景を指定しなければいけなくなるため、背面に画像を設置することができず、実用面でやや不便さがあります。
そこで、以下のSVGフィルターを利用したものを使用することで、上記の問題を解消することができます。
HTML
<div class="container">
<ul class="gooeys">
<li class="gooey"></li>
<li class="gooey"></li>
</ul>
</div>
HTMLはCSSのみの場合と全く同じものを使用していますが、以下のSVGのコードをインラインSVGとして、HTML内のどこか適当な所へ挿入する必要があります。
SVG
<svg>
<defs>
<filter id="filter">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/>
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="filter"/>
<feComposite in="SourceGraphic" in2="filter" operator="atop"/>
</filter>
</defs>
</svg>
上のSVGコードをそのままHTMLへ貼付けてしまえばOKです(場所はどこでもいい)。defs
タグで囲んでいますので、この部分が直接描画されることはありません。
上記の部分では、SVGの(原始)フィルタを重ね合わせ、効果をつくっています。filter
要素に設定してあるID(#filter)を、今度はCSSのfilter
要素のurlに指定することで、そのSVGの効果を利用できるようになります。
上記コードfilter
要素内のfeで始まる要素を原始フィルタと呼ぶようですが、この部分の設定は少々厄介なので、そのまま利用してしまうのがいいと思います。
CSS
.gooeys {
position: relative;
width: 400px;
height: 400px;
margin: 0 auto;
-webkit-filter: url('#filter');
filter: url('#filter');
}
.gooey {
position: absolute;
top: 0;
bottom: 0;
width: 120px;
height: 120px;
margin: auto;
background: #ff0000;
border-radius: 50%;
}
.gooey:first-child {
right: 50%;
}
.gooey:nth-child(2) {
left: 50%;
}
CSSのみの時と違う部分は、filter
要素の記述と、background
要素がないことで、それ以外は全く同じ内容となっています。
以下がそのデモになります。SVGを使った場合、背面の画像が違和感なく表示されていることが分かると思います。
デモ
See the Pen SVG filter gooey effect by ta$uya_42EG4M1 (@42EG4M1) on CodePen.
※上記のデモには、マウスホバーをするとアニメーションするエフェクトが追加されています。Chrome、Firefox(ともに最新版)以外のブラウザでは、正常に表示されない場合があります。
CSSのみのものと見比べると、背景が隠れてしまうこと以外に、円(丸)の大きさも違うことが分かると思います(もちろん、CSSでは、どちらも同じサイズを指定しています)。
まとめ
CSSのみのものとSVGを利用したものどちらを使うべきかは、利用シーンによっても変わってくると思いますが、SVGを利用したもののほうが、実用的であり、かつ、正確な表示ができそうに思います。
ただ、いずれにしても、ブラウザのサポートの問題がありますので、使用する際には注意が必要です。確認した中でアニメーションも含めて正常に表示されていたのは、FirefoxとChrome(共に最新版)だけで、SafariやIE11ではうまく表示できませんでした。スマホの場合も、Chromeアプリであれば問題ありませんでしたが、他のブラウザでは難しいと思われます。現時点では、もし使用するのであればフォールバック等が必要になってくるでしょうね。
JSを使ってアニメーションさせたものも載せたかったのですが、長くなってしまったのでまた次のネタとして取っておきたいと思います。