CSS animation で遊び倒す　- ボタン  Gooey Effect、Sass-

CSS animation day17 となりました。 

本日は、Gooey Effect を使って、別のボタンを作ります。

#1. 完成版
![ダウンロード (43).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/a05a56af-1e26-46f4-8302-fc94217a04e0.gif)


#2. 参考文献
[Codepen: Gooey Menu](https://codepen.io/lbebber/pen/LELBEo?editors=1100)

#3. 分解してみる

❶. 

まずは、[前回](https://qiita.com/duka/items/c3bd66c8741ec826cd0e) のコードを使って、ボタンを5つに増やしましょう。


```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="css/styles.css" />
    <link
      rel="stylesheet"
      href="https://use.fontawesome.com/releases/v5.7.1/css/all.css"
      integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <div class="container">
      <div class="gooey">
        <input type="checkbox" id="start" />
        <label for="start">
          <div class="menu-open-button">
            <i class="fas fa-plus plus"></i>
          </div>
        </label>
        <div class="circle1">
          <i class="far fa-envelope mail"></i>
        </div>
        <div class="circle2">
          <i class="far fa-question-circle question"></i>
        </div>
        <div class="circle3">
          <i class="far fa-envelope mail"></i>
        </div>
        <div class="circle4">
          <i class="far fa-question-circle question"></i>
        </div>
        <div class="circle5">
          <i class="far fa-question-circle question"></i>
        </div>
      </div>

      <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
        <defs>
          <filter id="filter">
            <feGaussianBlur
              in="SourceGraphic"
              stdDeviation="20"
              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 17 -7"
              result="filter"
            />
            <feBlend in="SourceGraphic" in2="filter" />
          </filter>
        </defs>
      </svg>
    </div>
  </body>
</html>
```

```styles.css
body {
  margin: 0;
  padding: 0;
}

.container {
  position: relative;
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gooey {
  width: 100%;
  height: 100vh;
  margin: 0 auto;
  filter: url("#filter");
}

.plus {
  font-size: 3em;
  color: #fff;
  padding: 27px 29px;
}

.mail {
  font-size: 3em;
  color: #fff;
  padding: 26px;
}

.question {
  font-size: 3em;
  color: #fff;
  padding: 26px;
}

#start {
  display: none;
}

.menu-open-button {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
  cursor: pointer;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  transition-duration: 400ms;
  transform: scale(1, 1);
  z-index: 2;
}

.menu-open-button:hover {
  transform: scale(1.1, 1.1);
}

.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
  transition: transform ease-out 200ms;
  transform: translate3d(0, 0, 0);
}
```

次に、これらにアニメーションを設定します。
イメージは、ボタンを押したら、下側に半円を描くようにボタンが動くようにします。

```styles.css
#start:checked ~ .circle2 {
  transform: translate3d(120px, 130px, 0);
  transition-timing-function: ease;
  transition-duration: 600ms;
}

#start:checked ~ .circle3 {
  transform: translate3d(0, 200px, 0);
  transition-timing-function: ease;
  transition-duration: 600ms;
}

#start:checked ~ .circle4 {
  transform: translate3d(-120px, 130px, 0);
  transition-timing-function: ease;
  transition-duration: 600ms;
}

#start:checked ~ .circle5 {
  transform: translate3d(-200px, 20px, 0);
  transition-timing-function: ease;
  transition-duration: 600ms;
}

#start:checked ~ div i {
  animation: blight 600ms ease-in forwards;
}

#start:checked + label div i {
  transform: rotateZ(-45deg);
  transition-timing-function: ease;
  transition-duration: 300ms;
}

@keyframes blight {
  0% {
    opacity: 0.6;
  }
  100% {
    opacity: 1;
  }
}
```

![ダウンロード (43).gif](https://qiita-image-store.s3.amazonaws.com/0/232715/ac7d523d-efc4-c1be-912f-2efc0a6d3f5b.gif)




できました！　

・・・

ただ、なんというか・・・
コードが長いです。読む気になりません。
どうにかリファクタリングできないでしょうか？
CSS　でループ文使えれば・・・　


ということで、Sass　を使ってみたいと思います。
Sass とは？という方は、[こちら](https://qiita.com/m0nch1/items/b01c966dd2273e3f6abe) がわかりやすいです。


エディターは、VSCode を使用しているため、Sass の導入は、[こちら](https://qiita.com/Y_ASAMOTO/items/d5f33ecf5bfbb7f028a5) を参考に、簡単に始められます。　

Live Sass Compiler を追加して、ファイルの名前をscss に変更し、
先ほどのcss を変更していきます。



① 継承　


```styles.scss
.circle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
}

.menu-open-button {
  @extend .circle;
  ...
}

.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
  @extend .circle;
  ...
}
```

緑丸ボタンの設定を、.circle{} として、作り
@extend で、circle 1~5 と, menu-open-button へ継承してます。　


別の書き方として、@mixin と @include を使った書き方もできます。

```styles.scss
@mixin circle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
}


.menu-open-button {
  @include circle;
  ...
}

.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
  @include circle;
  ...
}
```

こちらも同じ結果となります。
extend とかなり似てますが、何が違うのでしょうか？

@mixin, @include の場合、引数を使うことができ、

```styles.scss
@mixin icon($padding) {
  font-size: 3em;
  color: #fff;
  padding: $padding;
}
```

というように、設定でき

```styles.css
//before

.plus {
  font-size: 3em;
  color: #fff;
  padding: 27px 29px;
}

.mail {
  font-size: 3em;
  color: #fff;
  padding: 26px;
}

.question {
  font-size: 3em;
  color: #fff;
  padding: 26px;
}
```
このコードが、

```styles.scss

//after

.plus {
  @include icon(27px 29px);
}

.mail,
.question {
  @include icon(26px);
}
```
こう書けます！！
このように、@mixin, @includeを使えば、引数を与えて使いまわすことができます！


もっと詳しく知りたい方は、

[Web制作者のためのSassの教科書 改訂2版 Webデザインの現場で必須のCSSプリプロセッサ Web制作者のための教科書シリーズ](https://www.amazon.co.jp/Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AESass%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E6%94%B9%E8%A8%822%E7%89%88-Web%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AE%E7%8F%BE%E5%A0%B4%E3%81%A7%E5%BF%85%E9%A0%88%E3%81%AECSS%E3%83%97%E3%83%AA%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5-Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%B9%B3%E6%BE%A4-ebook/dp/B075LCKFLL/ref=pd_sim_351_1/357-9836615-0671601?_encoding=UTF8&pd_rd_i=B075LCKFLL&pd_rd_r=690c49bf-2a94-11e9-a596-cf6e4186fe84&pd_rd_w=ZgrSn&pd_rd_wg=XbGbA&pf_rd_p=b88353e4-7ed3-4da1-bc65-341dfa3a88ce&pf_rd_r=1QW37HJQNZGGTZ890P60&psc=1&refRID=1QW37HJQNZGGTZ890P60)

[hajipon.com](https://hajipion.com/1002.html) に大変わかりやすく書いてありましたので、ぜひご一読ください。
<br/> 
②　ネスト

Sass では、CSSを入れ子で書いていくことができます。
この機能で、コードの記述量が大幅に減り、メンテナンス性が向上するでしょう。ただし、使いすぎるとネストが深くなり、可読性が落ちるので、気をつけましょう！


```styles.css
//before


 body {
  margin: 0;
  padding: 0;
}

.container {
  position: relative;
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gooey {
  width: 100%;
  height: 100vh;
  margin: 0 auto;
  filter: url("#filter");
}

.plus {
  font-size: 3em;
  color: #fff;
  padding: 27px 29px;
}

.mail {
  font-size: 3em;
  color: #fff;
  padding: 26px;
}

.question {
  font-size: 3em;
  color: #fff;
  padding: 26px;
}

#start {
  display: none;
}

.menu-open-button {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
  cursor: pointer;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  transition-duration: 400ms;
  transform: scale(1, 1);
  z-index: 2;
}

.menu-open-button:hover {
  transform: scale(1.1, 1.1);
}

.circle1,
.circle2 {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
  transition: transform ease-out 200ms;
  transform: translate3d(0, 0, 0);
}

#start:checked ~ .circle1 {
  transform: translate3d(0, -150px, 0);
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  transition-duration: 800ms;
}

#start:checked ~ .circle2 {
  transform: translate3d(0, -300px, 0);
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  transition-duration: 800ms;
}

#start:checked ~ div i {
  animation: blight 600ms ease-in forwards;
}

#start:checked + label div i {
  transform: rotateZ(-45deg);
  transition-timing-function: ease;
  transition-duration: 300ms;
}

@keyframes blight {
  0% {
    opacity: 0.6;
  }
  100% {
    opacity: 1;
  }
}
```

```styles.scss
//after

body {
  margin: 0;
  padding: 0;
}

.container {
  position: relative;
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gooey {
  width: 100%;
  height: 100vh;
  margin: 0 auto;
  filter: url("#filter");
}

@mixin icon($padding) {
  font-size: 3em;
  color: #fff;
  padding: $padding;
}

.plus {
  @include icon(27px 29px);
}

.mail,
.question {
  @include icon(26px);
}

@mixin circle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: green;
}

.menu-open-button {
  @include circle;
  cursor: pointer;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  transition-duration: 400ms;
  transform: scale(1, 1);
  z-index: 2;
  &:hover {
    transform: scale(1.1, 1.1);
  }
}

.circle1,
.circle2,
.circle3,
.circle4,
.circle5 {
  @include circle;
  transition: transform ease-out 200ms;
  transform: translate3d(0, 0, 0);
}

#start {
  display: none;
  &:checked {
    transition-timing-function: ease;
    transition-duration: 600ms;
    ~ div i {
      animation: blight 600ms ease-in forwards;
    }
    + label {
      div i {
        transform: rotateZ(-45deg);
        transition-timing-function: ease;
        transition-duration: 300ms;
      }
    }
    ~ .circle1 {
      transform: translate3d(200px, 20px, 0);
    }
    ~ .circle2 {
      transform: translate3d(120px, 130px, 0);
    }
    ~ .circle3 {
      transform: translate3d(0px, 200px, 0);
    }
    ~ .circle4 {
      transform: translate3d(-120px, 130px, 0);
    }
    ~ .circle5 {
      transform: translate3d(-200px, 20px, 0);
    }
  }
}

@keyframes blight {
  0% {
    opacity: 0.6;
  }
  100% {
    opacity: 1;
  }
}
```

&: を使うことで、入れ子の書き方ができ、記述量が少なくなりました。ただし、やはり使いすぎると読みにくくなるので、注意が必要ですね。


本日はここまでです。
明日から、Sass をいっぱい使っていこうと思います。
それではまた明日〜