gaaamiiのブログ

間違ったことを書いている時があります。コメントやTwitter、ブコメなどでご指摘ください

CSSで雨を表現する

せっかくの4連休ですが、なんの予定もありません。まだまだあちこち外出するのは怖いです。しかも連休初日は雨です。散歩くらいはしようと思ってましたが、この雨だとやる気が削がれますね。せっかく暇で、外は雨が降っているので、雨をCSSで表現できたら良いなと思い、やってみました。

雨を見てみる

雨を見てみると、たくさんの水滴が上から下に落ちています。これをCSSで表現できればよさそうです。

たくさんの水滴

水滴は英語でwater dropのようなので、.drop というdivを用意しました。そしてこれがたくさん必要なのですが、HTMLにたくさん書くのはなんだかなと思って、一つだけ用意して、画面読み込み時にJavaScriptで任意の数にコピーするようにしました。

const createDrops = () => {
  const rain = document.querySelector('.rain')
  const drop = document.querySelector('.drop')
  const numberOfDrops = 150
  for (let i = 0; i < numberOfDrops; i++) {
    rain.appendChild(drop.cloneNode())
  }
}

window.onload = () => {
  createDrops();
}

上から下に落とす

次に、上から下に落とします。.drop要素が、margin-top: 0からmargin-top: 100vhへ移動すれば良さそうです。

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
}
.rain {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-between;
  position: fixed;
  opacity: 0.8;
}
.drop {
  width: 1px;
  height: 0vh;
  background: #999;  
  animation: falldown 1s infinite;
  height: 10vh;
}
@keyframes falldown {
  0% {
    margin-top: 0vh;
  }
  100% {
    margin-top: 100vh;
  }
}

水滴には見えませんが、たくさんのなにかが下に落ちているのでよさそうです。

雨粒っぽくする

これで雨です!というのは強引すぎるので、.drop をちゃんと雨粒っぽくしたいです。

上から下へ、揃って落ちていると雨っぽくありません。なのでどうにかしてそれをずらしたい。そこで、animation-delay プロパティを使います。.drop:nth-child(2n)で、偶数番目の.drop要素が落ちるタイミングを0.5秒遅くしてみます。

.drop:nth-child(2n) {
  animation-delay: .5s;
}

落ちるタイミングがずれましたが、まだ雨っぽくはないですね。なので、いっぱいずらします。

.drop:nth-child(2n) {
  animation-delay: .1s;
}
.drop:nth-child(3n) {
  animation-delay: .2s;
}
.drop:nth-child(4n) {
  animation-delay: .3s;
}
.drop:nth-child(5n) {
  animation-delay: .4s;
}
.drop:nth-child(6n) {
  animation-delay: .5s;
}
.drop:nth-child(7n) {
  animation-delay: .6s;
}
.drop:nth-child(8n) {
  animation-delay: .7s;
}
.drop:nth-child(9n) {
  animation-delay: .8s;
}
.drop:nth-child(10n) {
  animation-delay: .9s;
}

少しは雨っぽくなりました。ただ、なんて規則的な降り方をする雨なんだ、という感じがしますね。なので、ちょっと順番をいじくります。

.drop:nth-child(2n) {
  animation-delay: .3s;
}
.drop:nth-child(3n) {
  animation-delay: .9s;
}
.drop:nth-child(4n) {
  animation-delay: .2s;
}
.drop:nth-child(5n) {
  animation-delay: .1s;
}
.drop:nth-child(6n) {
  animation-delay: .5s;
}
.drop:nth-child(7n) {
  animation-delay: .4s;
}
.drop:nth-child(8n) {
  animation-delay: .7s;
}
.drop:nth-child(9n) {
  animation-delay: .8s;
}
.drop:nth-child(10n) {
  animation-delay: .6s;
}

まだまだ規則的ですが、こだわりだすと大変そうなのでこれで次に進みます。

色をつける

白地に黒い線が降っている状態なので、もう少し雨っぽくするため、背景に色をつけます。どんよりした色にしたいので、こんな感じにします。

body {
  background: linear-gradient(#666f6d, #999);
}

おお〜、これはだいぶ雨じゃないでしょうか。

仕上げ

あとは雰囲気でいじっただけなので割愛しますが、雨の落ち方やら色のことがわかっていれば、もっとリアルに雨を表現できそうです。

まとめ

普通のCSSなので、こいつの上に画像でものっけて透明度を調整すれば、雨の街みたいなのもできそうですね。横浜(みなとみらい)の画像をのっけてみるとこんな感じになりました。

See the Pen Rainy Yokohama by gaaamii (@gaaamii) on CodePen.