以前、アコーディオンを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の種類も選べるようになったので、より使いやすくなったと思います。