【Css】transfromを使ってハンバーガーメニューボタンを作ってみた

#初めに
モバイルメニューアイコンでよく見かけるハンバーガーメニューボタンをCssのtransformとtransitionを利用して学習した内容をもとに作ってみました。

※内容に間違いなどがある場合はご指摘をよろしくお願いします。

# やりたいこと
ハンバーガーメニューボタンをCssで作成し、クリックするとアニメーション効果でボタンの形が変わるようにしたい。

# 完成形のイメージ
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="redrabbit1104" data-slug-hash="QWppBdG" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Hamburger Menu Icon">
  <span>See the Pen <a href="https://codepen.io/redrabbit1104/pen/QWppBdG">
  Hamburger Menu Icon</a> by redrabbit1104 (<a href="https://codepen.io/redrabbit1104">@redrabbit1104</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# ハンバーガーメニューとは
主にモバイルメニューボタンとして使われるアイコン。 横棒が3本並んだ「≡」の形でハンバーガーに似ていることからハンバーガーメニューと呼ばれている。

# Point
1.横棒を3本並べ、メニューの形を作る
2.<b>メニューが変形した後の形を考える</b>
3.クリックした時にメニューの形が変わるようにする
4.クリック前（変形前）とクリック後（変形後）の間にアニメーション効果を適用する

# htmlを用意する
buttonタグの名前をmenu_buttonにし、その中にspanタグを3つ並べます。

```html
<body>
    <button class="menu_button">
        <span></span>
        <span></span>
        <span></span>
    </button>
    <script src="menu_button.js"></script>
</body>
```

# 初期状態のボタンの形を作る
まずbuttonタグに予め設定されている属性を消します。背景色(background-color)をunsetにして無くします。borderとoutlineも要らないのでnoneにします。また、ボタンにカーソルを当てた時に人差し指の形？にしたいのでpointerを指定します。

```scss
.menu_button {
  background-color: unset;
  border: none;
  outline: none !important;
  cursor: pointer;
  margin: 20px;
}
```
続いて横棒を3つ作ります。spanタグはinline要素なので、displayをblockにします。これをしないと表示領域が0になってしまいます。続いて棒の色をbackground-colorでblackにします。高さと幅もheightとwidthで適当にpx単位で決めます。棒と棒の間は間隔を空けたいので、margin-bottomを9pxにします。最後の3つ目の棒だけは下の間隔を空ける必要がないためmargin-bottomを0にしておきます。

```scss
.menu_button {
   //中略
  & > span {
    background-color: black;
    width: 35px;
    height: 4px;
    display: block;
    margin-bottom: 9px;
    &:last-child {
      margin-bottom: 0;
    }
  }
}
```

# menu_buttonをクリックした時にopenクラスを付与する
ボタンをクリックした時にopenというクラスをmenu_buttonに付けます。このopenというクラスに対してクリックした状態のメニューボタンの形をcssで調整します。そして、もう一度クリックした時にopenクラスが消えるようにします。そうするとopenクラスに対して記述したcssが適用されなくなるので、元のメニューボタンの形に戻ります。
javascriptで以下のように記述します。

```javascript
"use strict";

const btn = document.querySelector(".menu_button");
btn.addEventListener("click", () => btn.classList.toggle("open"));
```
btnという変数にmenu_button要素を格納します。そして、addEventListenerでclickした時に、menu_buttonにtoggleメソッドを使いopenクラスを付けたり外したりできるようにします。

# openクラスが付与された時のcssを記述
button_menuにopenクラスが付いた時のcssを記述します。これがハンバーガーメニューの変形後の形になります。openクラスの直下のspan要素に対してスタイルを適用したいので.open > spanとします。また、spanタグの1番目、2番目、3番目の要素それぞれに違う形のアニメーションを適用したいので&:nth-child(n)を使います。transition-delayをそれぞれ違う秒数に指定します。70ms,30ms,110ms遅れてアニメーションが適用されます。3本の横棒を最終的に短くしたいのでtransformプロパティーのscaleXで長さを調整します。上から順に0.4,0.5,0.7にして上から順に長くなるようにします。scaleXは左と右、両サイドが同時に短くなるのでアニメーション終了後は右にずれてしまいます。それを防ぐため、translateXを利用してずれた分、左側に戻します。（これは何度も実行してpxの値を調整します）最後に1番目と3番目の棒を360度回転させます。

```scss
.open > span {
  &:nth-child(1) {
    transition-delay: 70ms;
    transform: translateX(-10px) rotate(360deg) scaleX(0.4);
  }
  &:nth-child(2) {
    transition-delay: 30ms;
    transform: translateX(-9px) scaleX(0.5);
  }
  &:nth-child(3) {
    transition-delay: 110ms;
    transform: translateX(-5px) rotate(-360deg) scaleX(0.7);
  }
}
```
# menu_buttonのspanタグにtransitionを指定する
このままだと、ボタンをクリックした時に変形後の形が一瞬で行われてしまいます。これだと回転する動きや棒が縮む動きなどが見れなくなってしまうので、transitionプロパティーを使ってtransform（変形）が行われる時間を指定します。0.7秒に渡ってアニメーション効果が現れるようにしたいので、transform 0.7sとします。

```scss
.menu_button {
 　　//中略
  & > span {
 　　//中略
    transition: transform 0.7s;  //追記
    &:last-child {
      margin-bottom: 0;
    }
  }
}
```
#参考サイト
https://ri-mode.com/rainbow/2013/06/10/css3_keyframes_transform/
https://freefrontend.com/css-hamburger-menu-icons/
https://qiita.com/tomokichi_ruby/items/2460c5902d19b81cace5
https://developer.mozilla.org/ja/docs/Web/CSS/outline
https://developer.mozilla.org/ja/docs/Web/CSS/transition