【JS】アコーディオンをVanilla JS でやってみる
概要
前回同様にjQueryからVanillaJSへの切り替えとして、アコーディオンを忘備録としてメモ。
実装
サンプルとして、以下のような感じです。
html
<div class="accordion">
<h2 class="accordion__ttl">タイトル1</h2>
<div class="accordion__cnt">
<p>ここはコンテンツ</p>
</div>
<h2 class="accordion__ttl">タイトル2</h2>
<div class="accordion__cnt">
<p>ここはコンテンツ2</p>
<p>ここはコンテンツ2</p>
<p>ここはコンテンツ2</p>
</div>
<h2 class="accordion__ttl">タイトル3</h2>
<div class="accordion__cnt">
<p>ここはコンテンツ3</p>
</div>
</div>
Javascriptでクリックしたタイトルの次のコンテンツ要素をアコーディオンの対象とするため「accordion__ttl」と「accordion__cnt」を隣合わせにしています。
CSS(SCSS)
.accordion {
&__ttl {
background-color: #ffff00;
padding: 5px;
cursor: pointer;
transition: background-color 0.3s;
&:hover {
background-color: #ff0000;
}
&.is-active {
background-color: #ff0000;
}
}
&__cnt {
height: 0;
overflow: hidden;
transition: 0.2s ease height;
}
&__inner{
padding:20px;
}
}
クラス「accordion__cnt」がコンテンツの部分だが、display:none
にするのではなく、高さ(height
)を0にする。コンテンツの内容がはみ出るので、overflow: hidden
で隠すようにする。
アコーディオンのアニメーションさせるのに、transition
で高さ(height
)を指定する。
Javascript
const acc_ttl=Array.from(document.querySelectorAll(".accordion__ttl"));
for(let i=0; i< acc_ttl.length; i++){
let ttl=acc_ttl[i];
let content=ttl.nextElementSibling;
ttl.addEventListener("click",()=>{
ttl.classList.toggle("is-active");
if (content.style.height) {
content.style.height = null;
} else {
content.style.height = content.scrollHeight + 'px';
}
});
}
querySelectorAll
でタイトルとなる部分を取得。
アコーディオンで表示するコンテンツはnextElementSibling
で取得。
ele.nextElementSibling
でele
要素の次の要素が取得できる読み取り専用のプロパティ。
クリックイベントでは、タイトルをクリックしたらtoggle
でis-active
のクラスを切り替える。
今回のポイントとなるアコーディオンの部分は、content.scrollHeight
である。
ele.scrollHeight
は読み取り専用のプロパティで、はみ出た要素(overflowなど)など画面上に表示されていないコンテンツを含む要素の内容の高さ取得できる。
scrollHeightの値は、素のpaddingは含みますが、marginは含まれない。
このcontent.scrollHeight
を使うのですが、まずはコンテンツ要素の高さ(height
)を調べるのだが初期値はCSSで0にしているため、content.scrollHeight
で高さを設定する。ちゃんと「px」の値もつける。
次にクリックしたときはコンテンツ要素の高さ(height
)が設定されてるので、その値を「null」にしてあげる。
これでアコーディオンの完了となる。。
まとめ
以下のサイトを参考にさせていただきました。
Discussion