【脱jQuery】矢印付きアコーディオンをJavascriptのみで実装【コピペ】

こんにちは!Webディレクター兼エンジニアののせっち@nosecchi01です。

以前jQueryで矢印付きアコーディオンを実装する方法を解説しました。

お陰様で、当ブログ内では常にアクセス上位のページとなっています。

今回は、jQueryを使わずにJavascriptのみでアコーディオンメニューを実装する方法を解説します。

Javascriptに慣れている方にはクドい解説になっているかもしれませんが、
初心者の方向けに、かなり細かく解説をしていきます!

複数展開

早速コードペンで見てみましょう!

See the Pen Accordion (javascript ver) by Yuki Nose (@yukinouz1) on CodePen.

意外とjavascriptのコード量が少なく実現できていることがわかります。

Javascriptの解説

HTML, CSSは基本的な事しか書いていないので、主にJavascriptを解説していきます。

一点だけ、この記事内の解説では、

  • クリックする要素:javascript : ’.js-accordion-title’ css: accordion__title
  • 展開する要素:’.accordion__content’

となっています。これだけ頭に入れてください。

Javascriptコード全体像

まず、Javascriptのコード全体を見てみましょう!

document.addEventListener("DOMContentLoaded",() => {
  const title = document.querySelectorAll('.js-accordion-title');
  
  for (let i = 0; i < title.length; i++){
    let titleEach = title[i];
    let content = titleEach.nextElementSibling;
    titleEach.addEventListener('click', () => {
      titleEach.classList.toggle('is-active');
      content.classList.toggle('is-open');
    });
  }

});

大まかにはやっていることは下記の2つです!

  • ‘.js-accordion-title’ = クリックする要素を取得。
  • for分で要素一つ一つに対して、クリックイベント。

一つずつ見ていきましょう。

‘.js-accordion-title’ → クリックする要素を取得。

const title = document.querySelectorAll('.js-accordion-title');

document.querySelectorAllでクリックする要素である、’.js-accordion-title’を取得します。

クリックする要素は複数あるので、querySelectorAllを使います。

Document.querySelectorAll() MDN

https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll

for分で要素一つ一つに対して、クリックイベント。

for (let i = 0; i < title.length; i++){
    let titleEach = title[i];
    let content = titleEach.nextElementSibling;
    titleEach.addEventListener('click', () => {
      titleEach.classList.toggle('is-active');
      content.classList.toggle('is-open');
    });
  }

・title.lengthでtitleの数分繰り返すということです。

・let titleEach = title[i] の部分でtitleのindexを一つずつ代入しています。

・.nextElementSiblingは隣の要素を指しますので、’accordion__content’になります。

具体的には下記です。

<h4 class="accordion__title js-accordion-title">Accordion Title 1</h4> <!-- titleEach -->
<div class="accordion__content">Accordion Content 1</div> <!-- nextElementSibling -->
titleEach.addEventListener('click', () => {
  // この中の処理を行う
});

・titleEachをクリックしたら下記の処理を行いなさい。

titleEach.classList.toggle('is-active');
content.classList.toggle('is-open');

・titleEach.classList.toggle(‘is-active’); で’accordion__title’に’is-active’ クラスを付け外し。

・content.classList.toggle(‘is-open’); で’accordion__content’クラスを付け外しします。

toggleを使うことで、該当のクラスが無ければaddClass、あればremoveClassを行なってくれます。

少し違う書き方

コメントアウトにしていますが、下記でもOKです。

const title = document.querySelectorAll('.js-accordion-title');

  function toggle(){
  const content = this.nextElementSibling;
  this.classList.toggle('is-active');
  content.classList.toggle('is-open');
  }

  for (let i = 0; i < title.length; i++){
    title[i].addEventListener('click', toggle)
  }

こちらの場合は、toggle関数を定義しておいて、addEventListenerで呼び出す形です。

こちらの方が、順序がハッキリしてわかりやすいかもしれませんね!

考え方は同じなので、どちらでもOKです!

一つ開いたら他は閉じる

少し複雑になります。

See the Pen Accordion Single (javascript ver) by Yuki Nose (@yukinouz1) on CodePen.

Javascriptコード全体像

const accSingleTriggers = document.querySelectorAll('.js-acc-single-trigger');

accSingleTriggers.forEach(trigger => trigger.addEventListener('click', toggleAccordion));

function toggleAccordion() {
  const items = document.querySelectorAll('.js-acc-item');
  const thisItem = this.parentNode;

  items.forEach(item => {
    if (thisItem == item) {
      thisItem.classList.toggle('is-open');
      return;
    }
    item.classList.remove('is-open');
  });
}

jsの構成は下記のようになっています。

一つだけ開くアコーディオンの場合は、クリックした要素の親要素(prarentNode)にis-openクラスを付けます。

  • クリックした要素の親と、一致したときのみis-openクラスを付与
  • それ以外の要素はis-openクラスを外す

という構成です。

最初の要素は開いておく

こちらは2行追加するだけです!

See the Pen Accordion open first content(Javascript ver) by Yuki Nose (@yukinouz1) on CodePen.

Javascriptコード全体像

const accSingle = document.querySelector('.js-acc-single');
const items     = accSingle.querySelectorAll('.js-acc-item');
const accSingleTriggers = accSingle.querySelectorAll('.js-acc-single-trigger');

// 最初の要素を開いておく
const firstChild = accSingle.firstElementChild;
firstChild.classList.add('is-open');

accSingleTriggers.forEach(trigger => trigger.addEventListener('click', toggleAccordion));

function toggleAccordion() {
  const thisItem = this.parentNode;

  items.forEach(item => {
    if (thisItem == item) {
      thisItem.classList.toggle('is-open');
      return;
    }
    item.classList.remove('is-open');
  });
}

firstElementChildでアコーディオンの最初の要素を取得しておき、is-openクラスをつけておくだけです。

これは簡単ですね!

Javascriptのおすすめ勉強法

学習サイトとしてはドットインストールがオススメです。

僕は基本Progate派なのですが、Javascriptに関してはドットインスールが最適です。

  • とにかく講座数が多い(課金は必須)
  • 実際にアプリを作りながら学べるので実践に近い
  • よく使う技術は何度も出てくるため、自然と覚えられる

ドットインストールは、「ん?それ習ってないぞ・・・?」と言うのがいきなり出てきたりするのが難点ではありますが、Javascriptに関しては、レッスン数が多いため、数をこなして覚えていくのがいいと思います。

Javascriptのオススメ書籍

Javascriptでオススメの書籍はこちらです。

正直内容はツマラナイのですが・・・。

タイトル通り「コードレシピ集」となっており、辞書的に使うのに最適です!

上記のドットインストールと合わせて使うことで、内容を補完し合えるのでオススメです。

まとめ

  • バニラjsでも意外と少ないコードで書く事ができる
  • jQueryは便利

この記事を書いた人

のせっち

福岡県出身。早稲田大学卒。創業100年の鉄鋼商社でバンコク駐在最年少抜擢。毎日擦り切れるまで働かなくても幸せに生きている人々を見てフリーランスになりました。
現在は、主にバンコクでWeb制作、物販を中心に生きています。