アコーディオンメニュー（haml,scss,javascript）

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ CSSの基礎知識が増える
・ アコーディオンメニューの作り方について

## 例

例えば、こんな画面があったとします

![スクリーンショット 2020-11-21 13.41.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/526cfa22-5baf-e942-8a51-1f2e0b1637da.png)

## 手順
＊説明に必要な所だけ記述しています

① アコーディオンメニューをクリックしたら、表示する場所を予め記述します
→ 今回、アコーディオンメニューが`%a`だとすると、`.answer`配下の`%p fuga`

```haml:index.haml
.wrapper
  .wrapper__text
    %i.far.fa-envelope-open
    %h2 よくある質問
  .wrapper__question
    %a
      %i.far.fa-question-circle
      %p hoge?
    .answer
      %p fuga
```

② ①で記述した要素をアコーディオンメニュークリック後に表示させたいので、`display: none;`で隠しておきます

```scss:index.scss
.answer {
  display: none;
}
```

③ アコーディオンメニューをクリックしたら.activeクラスをつけると想定して、`display: block;`を指定します

```scss:index.scss
.answer.active {
  display: block;
}
```

④ hamlにJavaScriptファイルを読み込む記述と、accordion.jsファイルを新規作成します

```haml:index.html
= javascript_pack_tag 'accordion'
```

⑤ accordion.jsに処理を記述します

```javascript:accordion.js
const accordionMenu = document.querySelectorAll(".wrapper__question > a"); // アコーディオンメニュー発火部分をCSSのセレクタで要素を取得する変数

for (let i = 0; i < accordionMenu.length; i++) { // querySelectcorAllで要素を配列で取得して、変数"accordionMenu"の数だけ処理をfor文で繰り返す
  accordionMenu[i].addEventListener("click", function () {
    this.nextElementSibling.classList.toggle("active"); // イベントが起こっている要素の次のクラスを切り替える
  });
}
```

⑥ `%a`タグに`href`属性があり、クリック後にページがリロードしてしまう場合は、以下のように記述します

```javascript:accordion.js
const accordionMenu = document.querySelectorAll(".wrapper__question > a");

for (let i = 0; i < accordionMenu.length; i++) {
  accordionMenu[i].addEventListener("click", function (e) { // ファンクションに引数"e"（名前は自由）を持たせタグのイベントを取得する
    e.preventDefault(); // hrefのイベントをキャンセルする
    this.nextElementSibling.classList.toggle("active");
  });
}
```

アコーディオンメニューの機能自体はこれで完成していますが、右端の矢印を回転させる処理を記述します

![次に矢印.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/74f14115-82c3-ea6b-d5f1-c65d3606cdeb.gif)

⑦ accordion.js及び、index.scssを以下のように記述します

```javascript:accordion.js
const accordionMenu = document.querySelectorAll(".wrapper__question > a");

for (let i = 0; i < accordionMenu.length; i++) {
  accordionMenu[i].addEventListener("click", function () {
    this.classList.toggle("active"); // クリックした要素(a)自体に"active"クラスを切り替える
    this.nextElementSibling.classList.toggle("active");
  });
}
```

```scss:index.scss
    a.active::after {
      transform: rotate(180deg);
    }
```

これでアコーディオンメニューをクリックしたら、矢印がクルクル回転する様になりました

![矢印がくるくる.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/c95823f9-fd4b-18d8-639f-06c91dbd9545.gif)

## 参考（今回のコード）

```haml:index.haml
.wrapper
  .wrapper__text
    %i.far.fa-envelope-open
    %h2 よくある質問
  .wrapper__question
    %a
      %i.far.fa-question-circle
      %p hoge?
    .answer
      %p fuga
= javascript_pack_tag 'accordion'
```

```scss:index.scss
.wrapper {
  text-align: center;
  padding: 4rem 0;
  letter-spacing: 2px;
  &__text {
    i {
      font-size: 1.5rem;
      margin-right: -5px;
      vertical-align: 3px;
    }
    h2 {
      font-size: 1.75rem;
      font-weight: bold;
      display: inline-block;
    }
  }
  &__question {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-top: 3rem;
    a {
      font-size: 1.25rem;
      font-weight: bold;
      border: 1px solid #ddd;
      padding: 1rem 1.5rem;
      width: 70%;
      margin-bottom: 0.3rem;
      text-align: left;
      i {
        color: #016ea9;
        margin-right: -10px;
      }
      p {
        display: inline-block;
      }
    }
    a::after {
      content: "\02228";
      color: #ccc;
      float: right;
    }
    a:hover > p {
      text-decoration: underline;
    }
    .answer {
      width: 70%;
      text-align: left;
      padding: 1rem 1rem 2rem;
      display: none;
      p {
        font-weight: bold;
        color: #333;
      }
    }
    .answer.active {
      display: block;
    }
    a.active::after {
      transform: rotate(180deg);
    }
  }
}
```

```javascript:accordion.js

const accordionMenu = document.querySelectorAll(".wrapper__question > a");

for (let i = 0; i < accordionMenu.length; i++) {
  accordionMenu[i].addEventListener("click", function () {
    this.classList.toggle("active");
    this.nextElementSibling.classList.toggle("active");
  });
}
```