アコーディオンをjQueryなしで実装する 改善版

アコーディオンをjQueryなしで実装する 改善版

以前、アコーディオンをjQueryなしで実装するという記事を書きました。以前の記事での実装方法はheightを少しずつ足したり、引いたりしてアコーディオンを実装するというものでした。
ですので、少しJavascriptの内容が複雑になっていました。

今回はcssのtransitionを使って実装することでより簡単なコードで実装することができます。

htmlとcssの内容は以前のアコーディオンをjQueryなしで実装すると変わらないので、Javascriptのコードだけ載せます。

実装例

See the Pen accordion v2 by takblog (@blanks-site) on CodePen.

javascript

コードをクリップボードにコピー
(function(){
  const accordionBtns = document.querySelectorAll('.js-accbtn');
  const accordionBtnOpenClass = 'open';
  const accordionOpen = (id) =>{
    const contents = document.querySelectorAll('.js-acccontent[data-acc="'+id+'"]');
    contents.forEach((element)=>{
      element.style.display = 'block';
      element.style.overflow = 'hidden';
      const height = element.clientHeight;
      element.style.height = '0';
      element.style.transition = '.3s height ease';
      setTimeout(()=>{
        element.style.height = height+'px'; 
        setTimeout(()=>{
        element.style.height = 'auto'; 
        },300);        
      },10);
    });
  };
  const accordionClose = (id) => {
    const contents = document.querySelectorAll('.js-acccontent[data-acc="'+id+'"]');
    contents.forEach((element)=>{
      const height = element.clientHeight;
      element.style.height = height+'px'; 
      setTimeout(()=>{
        element.style.height = '0';
        setTimeout(()=>{
        element.removeAttribute('style'); 
        },300);        
      },10);
    });
  };
  accordionBtns.forEach((element)=>{
    element.addEventListener('click',(event)=>{
      const btn = event.currentTarget;
      const id = btn.dataset.acc;
      if(id != null && id != '' && id != undefined){
        if( btn.classList.contains(accordionBtnOpenClass) ){
          btn.classList.remove(accordionBtnOpenClass);
          accordionClose(id);
        }else{
          btn.classList.add(accordionBtnOpenClass);
          accordionOpen(id);
        }
      }
    });
  });
})();

下記の説明はこちらのコードを開いていて、確認してください

3行目はアコーディオンがオープンになった時に「.js-accbtn」に付くclassになっています。

accordionOpen関数(4〜19行)

引数の「id」は.js-accbtnのdata-acc属性を取得しています。

5行目、取得したidと同じdata-acc属性値を持つ「.js-acccontent」をすべて取得しています。

6行目、.js-acccontentはquerySelectorAllで取得したので、forEachでループを回しています。

7、8行目、まず「.js-acccontent」にdisplay :block ;とoverflow: hidden ;を適用しています。

9行目「.js-acccontent」の高さを取得して、heightに入れています。display :block ;を適用してからじゃないと、高さが取得できないので、記述の順番には気をつけます。

10行目、「.js-acccontent」の高さを一度0にします。

11行目、「.js-acccontent」にtransition: .3s height ease;を適用します。ここを変更すればアコーディオンのスピードやEasingの種類を変更できます。

13行目、ほんの少しだけ時間を置いて、「.js-acccontent」の高さに、9行目で取得したheightを適用します。

14〜16行目、transitionで設定した時間(ここでは0.3秒)が経ったら、「.js-acccontent」のheightをautoに変更します。ここの記述はなくても大丈夫ですが、アコーディオンを開いた後に、ウィンドウ幅が変わるなどして、コンテンツ内の高さが変わった場合に、height:〇〇px;のままだと崩れが起きるので、崩れを防ぐために入れています。

accordionClose(20〜32行)

accordionOpen関数と同じで、引数の「id」は.js-accbtnのdata-acc属性を取得しています。

23行目、「.js-acccontent」の高さを取得して、heightに入れています。

24行目、23行目で取得したheightを「.js-acccontent」に適用しています。height:auto;からheight:0;にしてもtransitionは正常に動かないので、一度ちゃんとした値を入れます。

25行目、ほんの少しだけ時間を置いて、「.js-acccontent」のheightを0にします。

27〜29行目、transitionで設定した時間(ここでは0.3秒)が経ったら、「.js-acccontentに設定したstyleをすべて削除します。

33〜47行目

「.js-accbtn」をクリックした時に、「.js-accbtn」に3行目のclassが付いているか、付いていないかでaccordionOpen関数を呼び出すか、accordionClose関数を呼び出すか、を判定しています。


cssのtransitionを用いることで、前回のアコーディオンよりもだいぶ分かりやすく、簡単にアコーディオンの実装ができました。それのtransitionを用いているので、Easingの種類も選べるようになったので、より使いやすくなったと思います。

arrow_circle_up