ザリガニデザインオフィス

CSSで水面のようなアニメーションのサムネイル

CSSで水面のようなアニメーション

ゆらゆらと水面が揺らめく感じです。IEは残念ながら非対応(対応方法あり)。

デモはこちら

コードは以下になります。(ここでは下方互換のベンダープレフィックスなどは省略しています)

HTML

<figure class="minamo">
  <div class="water"></div>
  <div class="wave wave1"></div>
  <div class="wave wave2"></div>
</figure>

CSS

.minamo {
  width: 512px;
  height: 512px;
  margin: 20px auto;
  position: relative;
  z-index: 0;
}
.water {
  width: 100%;
  height: 100%;
  position: absolute;
  background: linear-gradient(
    180deg,
    rgb(47, 154, 237) 0%,
    rgb(138, 225, 252) 100%
  );
  z-index: 1;
}
.wave {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  right: 0;
  background-image: url("./img/wave.png");
  background-repeat: repeat;
  animation-timing-function: linear;
  animation-duration: 7s;
  animation-iteration-count: infinite;
  filter: blur(3px);
}
.wave1 {
  z-index: 2;
  animation-name: wave1;
}
.wave2 {
  z-index: 3;
  animation-name: wave2;
  transform: scale(-1, 1);
}
@keyframes wave1 {
  0% {
    background-position: 0 0;
    opacity: 0.4;
  }
  50% {
    background-position: 50% 50%;
    opacity: 0.6;
    filter: blur(4px);
  }
  100% {
    background-position: 100% 100%;
    opacity: 0.4;
  }
}
@keyframes wave2 {
  0% {
    background-position: -20% 0;
    opacity: 0.6;
    filter: blur(4px);
  }
  50% {
    background-position: -70% -50%;
    opacity: 0.4;
    filter: blur(3px);
  }
  100% {
    background-position: -120% -100%;
    opacity: 0.6;
    filter: blur(5px);
  }
}

作り方

まず、水面の模様に以下のような画像を作ります。(以下の画像は視認性を高めるために灰色の背景を敷いていますが、実際には白色透過の画像になります)

波紋の画像

画像サイズは自由ですが、タテヨコに並べるのでシームレスである必要があります。作るのが面倒であればこの画像を使ってください。CC0のライセンスの基、ご自由にご利用いただけます。

HTMLにはfigureタグに囲まれた要素がありますが、これが水面です。中には3つdivがありますが、それぞれ「背景のグラデーション」「波」「波(反転)」となっています。それらをpositonを使って1つに重ねています。

一番下のグラデーションですが、ここではCSSのグラデーションを使って表現していますが、グラデーションでなくても画像でも大丈夫です、背景の青はお好みで調節してください。

波ですが、先程の画像を背景として読み込み、repeatさせています。そしてアニメーションを7秒間で動かしています。定常的な動きにしたいのでanimation-timing-function: linearanimation-iteration-count: infiniteを指定しています。

ここでポイントになってくるのが、CSSフィルターのブラー(ぼかし)を使っている点です。上記の画像ははっきりした白い線ですが、ブラーをかけることでぼんやりとした感じにしています。画像でぼかすのではなく、CSSでフィルターをかけたのは、アニメーションで使いたかったからです。

wave1とwave2の違いとしてz-indexとアニメーションのほかにtransform :scale()を使っています。これは大きさを変えるというよりも画像の左右を反転させるために使っています。

同じ画像を使うと、秒数や動きが違っていても一定の間隔でぴったり一致してしまうところが出てきてしまいます。2種類の違う画像を用意すれば良いのですが、手っ取り早く左右反転させれば一致しないので、scaleの値を-1にしています。これで画像の読み込みも1つで済みます。

アニメーションですが、background-positionの値を変えてwave1では右下へ、wave2では左上(左右反転させているので、実際は右上)に動かしています。wave2は反転していますが、開始位置をずらすため-20%から始めて-120%で終わらせています。

opacityfilter: blurについても少し変化させています。wave1とwave2がそれぞれ逆になることで、ゆらゆらと揺れる水面を表現しています。

どうぶつの森っぽい

お気づきの方もいるかもしれませんが、最近話題のどうぶつの森ポケットキャンプをやっている時に思いつき、参考にしました。

IE11対応

IE11はCSS:filterに対応していないのでblurが効きません。そのため、IEに対応するためには画像自体にぼかしをかければ可能です。アニメーションでぼかしの揺らぎが出ないので若干クオリティは下がりますが、問題ないレベルではないでしょうか。

描画負荷は高め

CSS filterやアニメーションを使っているので描画負荷は高めです。自分のiPhone7で見てもカクついたりはしませんが、裏側でCPU(とGPU)が働いているはずです。以下はとあるiMacのCPUの使用率ですが、左側がアイドル状態、真ん中の台地状の部分が閲覧時(最後は閉じてます)、右側の山型は普通のサイトを閲覧している時です。

CPUの負荷のグラフ

厳密な計測ではないですが、普通のサイトを閲覧するよりはCPU負荷が高くなっています。その他のアニメーションとの併用や全面的に使用する場合などは少し注意が必要かもしれません。特にスマホでは電池の消耗が早くなったり、本体が熱くなったりする可能性があります。

どうぶつの森のような、ゆったりとしたサイトに利用すると良いかもしれませんね。