CSSだけで作る、液体っぽくポワポワ動く背景


これは何

  • 以下に貼ったような背景を、CSSだけで作るための記事です
    • タイトルの分かりづらさは私の語彙の無さが招いた結果です

ちなみにコードはGitHubに上げてあります。

方針

blur()contrast()を組み合わせる

ほとんどこれに尽きます。

作り方

1. まずは動く丸を作る

以下のHTMLとCSSを書くことで得られるのは

  • 塗りつぶしの丸とボーダーつきの丸がバラバラのタイミングで動く
  • ただし端が触れてもくっつかない状態
index.html
<body>
  <div class="wrapper">
    <div class="circlesWrapper">
      <div class="circle circleHorizontal circle1"></div>
      <div class="circle circleHorizontal circle2"></div>
      <div class="circle circleHorizontal circle3"></div>
      <div class="circle circleHorizontal circle4"></div>
      <div class="circle circleHorizontal circle5"></div>
      <div class="circle circleHorizontal circle6"></div>
      <div class="circle circleVertical circle7"></div>
      <div class="circle circleVertical circle8"></div>
      <div class="circle circleVertical circle9"></div>
      <div class="circle circleVertical circle10"></div>
      <div class="circle circleVertical circle11"></div>
      <div class="circle circleVertical circle12"></div>
    </div>
  </div>
</body>

`css:style.css
.wrapper {
height: 100%;
margin: auto;
overflow: hidden;
position: relative;
width: 100vw;
}

.circlesWrapper {
background-color: #fff;
display: flex;
height: 100%;
margin: auto;
position: relative;
width: 100%;
}

.circle {
border-radius: 50%;
height: calc(100vh / 13);
position: absolute;
width: calc(100vh / 13);
}

.circleHorizontal {
background-color: #000;
border: calc(100vh / 13 / 2) solid #000;
}

.circleVertical {
border: calc(100vh / 13 / 2) solid #000;
}

@keyframes horizontal {
from {
transform: translateX(0);
}
to {
transform: translateX(100vw);
}
}

@keyframes vertical {
from {
transform: translateY(0);
}
to {
transform: translateY(100vh);
}
}

.circle1 {
animation: horizontal 5s ease-in-out infinite alternate both;
left: calc(100vh / 13 / -1);
top: calc(100vh / 13 * 0.5);
}

/*
以下、位置を微妙にずらしたcircle2からcircle12を定義しています
今回はちゃちゃっと作りたかったので生のCSSで手書きで定義しているけど、実践ではSassでforとかを使った方が良いと思われます
*/
`

2. 丸を囲っている要素にfilterをかける

style.css
  .circlesWrapper {
    background-color: #fff;
    display: flex;
    height: 100%;
+   filter: blur(10px) contrast(20);
    margin: auto;
    position: relative;
    width: 100%;
  }

原理を説明すると、まずはblurがかかることでこのような見た目になります

gifに変換しているので若干見づらいですが、端がぼんやりしましたね。
この状態でcontrastを上げることで輪郭が吸着したような見た目になるという理屈です。

3. 色をつける

まだこの状態だと白黒ですが、単に丸に背景色として#55c500を指定すると……。

contrastをかけているので、色味まで変化してしまうみたいです。

これを回避するために(やや不本意ではありますが)空のdivを用意して

index.html
  <body>
    <div class="wrapper">
      <div class="circlesWrapper">
        <div class="circle circleHorizontal circle1"></div>
        <div class="circle circleHorizontal circle2"></div>
        <div class="circle circleHorizontal circle3"></div>
        <div class="circle circleHorizontal circle4"></div>
        <div class="circle circleHorizontal circle5"></div>
        <div class="circle circleHorizontal circle6"></div>
        <div class="circle circleVertical circle7"></div>
        <div class="circle circleVertical circle8"></div>
        <div class="circle circleVertical circle9"></div>
        <div class="circle circleVertical circle10"></div>
        <div class="circle circleVertical circle11"></div>
        <div class="circle circleVertical circle12"></div>
      </div>
+     <div class="cover"></div>
    </div>
  </body>

CSSも追加します。

style.css
.cover {
  content: "";
  background-color: #55c500;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  mix-blend-mode: lighten;
}

動いている丸の全面に#55c500で塗りつぶした色面を用意して、mix-blend-mode: lightenをかける。
すると黒で塗られている場所だけに#55c500が適用され、冒頭で貼ったgifと同じ見た目になります。

注意

例で貼ってあるgifはChromeで見たときの見た目です。

このコードと全く同じものを使うとFireFoxでは端が滲み、Safariではガビガビします。
ご注意ください。