Help us understand the problem. What is going on with this article?

アコーディオンメニュー(haml,scss,javascript)

はじめに

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

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

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

スクリーンショット 2020-11-21 13.41.00.png

手順

*説明に必要な所だけ記述しています

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

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;で隠しておきます

index.scss
.answer {
  display: none;
}

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

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

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

index.html
= javascript_pack_tag 'accordion'

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

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属性があり、クリック後にページがリロードしてしまう場合は、以下のように記述します

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

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

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");
  });
}
index.scss
    a.active::after {
      transform: rotate(180deg);
    }

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

矢印がくるくる.gif

参考(今回のコード)

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'
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);
    }
  }
}
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");
  });
}
s79ns
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away