なにかと実装する機会の多いアコーディオンパネル。
最近ではCSSだけでも実装できると聞いて試してみました。
ネイティブのJavaScript、jQueryでの実装方法も備忘録として残します。
JavaScript アコーディオンパネル
ネイティブのJavaScriptで動かすアコーディオンパネルです。
下記の流れで動作する形となっています。
- 開閉ボタン<div class=”accordion__head”>をクリック。
- 親要素<li class=”accordion__item”>にactiveというclassが付与される。
- アコーディオンの閉じている部分<div class=”accordion__body”>に当たるスタイルが変わる。(heightが0からautoに、paddingが上下0pxから上下10pxに)
動作サンプル
See the Pen Untitled by Yoshihiro Hotta (@yoshihiro-hotta) on CodePen.
HTML
<ul class="accordion__list">
<li class="accordion__item">
<div class="accordion__head">
<p>アコーディオン1の開閉ボタン</p>
</div>
<div class="accordion__body">
<p>アコーディオン1の中身</p>
</div>
</li>
<li class="accordion__item">
<div class="accordion__head">
<p>アコーディオン2の開閉ボタン</p>
</div>
<div class="accordion__body">
<p>アコーディオン2の中身</p>
</div>
</li>
<li class="accordion__item">
<div class="accordion__head">
<p>アコーディオン3の開閉ボタン</p>
</div>
<div class="accordion__body">
<p>アコーディオン3の中身</p>
</div>
</li>
</ul>
CSS
/*
アコーディオンそのものの横幅と余白を指定。
開閉動作に影響なし。
*/
.accordion__list {
width: 500px;
padding: 10px;
}
/*
アコーディオンの2つ目以降、上に余白を取る。
開閉動作に影響なし。
*/
.accordion__item:nth-child(n+2) {
margin-top: 10px;
}
/*
アコーディオンの開閉ボタンの装飾。
position: relative;が無いと、
「+」「-」の位置がずれるので注意。
*/
.accordion__head {
position: relative;
width: 100%;
padding: 10px;
color: #fff;
background: #019ac6;
cursor: pointer;
}
/*
アコーディオンの開閉ボタンの右側に「+」を表示。
*/
.accordion__head::after {
content: "+";
position: absolute;
top: 8px;
right: 10px;
}
/*
アコーディオンが開いた際に、
開閉ボタンの右側に「+」を「-」に変更する。
*/
.accordion__item.active .accordion__head::after {
content: "-";
right: 13px;
}
/*
アコーディオンの閉じている部分の装飾。
height: 0; overflow: hidden;にすることで、
通常時は表示されないようにする。
*/
.accordion__body {
overflow: hidden;
width: 100%;
height: 0;
padding: 0 10px;
background: #e8e8e8;
transition: all .25s ease;
}
/*
アコーディオンが開いた際に、
heightを0からautoに、paddingの上下を0から10に。
*/
.accordion__item.active .accordion__body {
height: auto;
padding: 10px;
}
JavaScript
// 厳格モードで実行
"use strict";
// アコーディオンパーツ全体と、開閉ボタンとなる部分のDOMを変数に格納。
const accordionItem = document.getElementsByClassName("accordion__item");
const accordionBtn = document.getElementsByClassName("accordion__head");
// 開閉ボタンがクリックされたときの処理。
// 開閉ボタンの数だけ処理できるようfor文を回す。
// accordionBtn[i](i部分には何番目のアコーディオンボタンか、の数字が入る)がクリックされた際、
// accordionItem[i](アコーディオンボタンと同じ数字のアコーディオンパーツ)に
// activeというcssのclassを付与する。
for(let i = 0; i < accordionBtn.length; i++) {
accordionBtn[i].addEventListener("click", function() {
accordionItem[i].classList.toggle("active");
});
}
jQuery アコーディオンパネル
jQueryで動かすアコーディオンパネルです。
やっていること自体はJavaScriptと同じですが、こちらではfor文を回すのではなく開閉ボタンの親要素のDOMをparentメソッドで取得して、activeを付与する形にしています。
動作サンプル
See the Pen Untitled by Yoshihiro Hotta (@yoshihiro-hotta) on CodePen.
HTML
<ul class="accordion__list">
<li class="accordion__item">
<div class="accordion__head">
<p>アコーディオン1の開閉ボタン</p>
</div>
<div class="accordion__body">
<p>アコーディオン1の中身</p>
</div>
</li>
<li class="accordion__item">
<div class="accordion__head">
<p>アコーディオン2の開閉ボタン</p>
</div>
<div class="accordion__body">
<p>アコーディオン2の中身</p>
</div>
</li>
<li class="accordion__item">
<div class="accordion__head">
<p>アコーディオン3の開閉ボタン</p>
</div>
<div class="accordion__body">
<p>アコーディオン3の中身</p>
</div>
</li>
</ul>
CSS
/*
アコーディオンそのものの横幅と余白を指定。
開閉動作に影響なし。
*/
.accordion__list {
width: 500px;
padding: 10px;
}
/*
アコーディオンの2つ目以降、上に余白を取る。
開閉動作に影響なし。
*/
.accordion__item:nth-child(n+2) {
margin-top: 10px;
}
/*
アコーディオンの開閉ボタンの装飾。
position: relative;が無いと、
「+」「-」の位置がずれるので注意。
*/
.accordion__head {
position: relative;
width: 100%;
padding: 10px;
color: #fff;
background: #F5675B;
cursor: pointer;
}
/*
アコーディオンの開閉ボタンの右側に「+」を表示。
*/
.accordion__head::after {
content: "+";
position: absolute;
top: 8px;
right: 10px;
}
/*
アコーディオンが開いた際に、
開閉ボタンの右側に「+」を「-」に変更する。
*/
.accordion__item.active .accordion__head::after {
content: "-";
right: 13px;
}
/*
アコーディオンの閉じている部分の装飾。
height: 0; overflow: hidden;にすることで、
通常時は表示されないようにする。
*/
.accordion__body {
overflow: hidden;
width: 100%;
height: 0;
padding: 0 10px;
background: #e8e8e8;
transition: all .25s ease;
}
/*
アコーディオンが開いた際に、
heightを0からautoに、paddingの上下を0から10に。
*/
.accordion__item.active .accordion__body {
height: auto;
padding: 10px;
}
jQuery
// ページの全てのDOM要素が読み込まれて、初期化されてから実行。
$(document).ready(function() {
// アコーディオン開閉ボタンのDOMを変数に格納。
const accordionBtn = $(".accordion__head");
// アコーディオン開閉ボタンがクリックされると、
// 開閉ボタンの親要素(accordion__item)に、
// activeというcssのclassが付与される。
accordionBtn.on("click", function() {
$(this).parent().toggleClass("active");
});
});
CSSオンリー アコーディオンパネル
HTMLとCSSのみで動かすアコーディオンパネルです。
JavaScript、jQueryを使ったアコーディオンパネルと大きく違う点として、開閉ボタン部分がinputタグ(checkbox)とlabelタグになっています。
JavaScriptを一切使わないため、これまでのようにDOMに対してclassを付与することで、当たるスタイルを変える事はできません。
そのため、CSSの隣接兄弟結合子を使って、開閉ボタンと隣り合っているアコーディオンの閉じている部分に当たるスタイルを、checkboxにチェックが入っているかどうかで切り替える仕組みです。
流れとしては下記のような形となります。
- 開閉ボタンのラベル<label class=”accordion__head” for=”accordion-1″>をクリック。
- 連動するチェックボックス<input type=”checkbox” class=”accordion__input” id=”accordion-1″>が、チェックが入った状態になる。
- アコーディオンの閉じている部分<div class=”accordion__body”>に当たるスタイルが変わる。(heightが0からautoに、paddingが上下0pxから上下10pxに)
動作サンプル
See the Pen Untitled by Yoshihiro Hotta (@yoshihiro-hotta) on CodePen.
HTML
<ul class="accordion__list">
<li class="accordion__item">
<!--
type="checkbox"、id="accordion-1"のinputタグと
for="accordion-1"のlabelタグを用意する。
checkboxにチェックが付いたことを検知して、
アコーディオンの隠れている部分の高さを変える。
-->
<input type="checkbox" class="accordion__input" id="accordion-1">
<label class="accordion__head" for="accordion-1">アコーディオン1の開閉ボタン</label>
<div class="accordion__body">
<p>アコーディオン1の中身</p>
</div>
</li>
<li class="accordion__item">
<!-- -->
<input type="checkbox" class="accordion__input" id="accordion-2">
<label class="accordion__head" for="accordion-2">アコーディオン2の開閉ボタン</label>
<div class="accordion__body">
<p>アコーディオン2の中身</p>
</div>
</li>
<li class="accordion__item">
<!-- -->
<input type="checkbox" class="accordion__input" id="accordion-3">
<label class="accordion__head" for="accordion-3">アコーディオン3の開閉ボタン</label>
<div class="accordion__body">
<p>アコーディオン3の中身</p>
</div>
</li>
</ul>
CSS
/*
アコーディオンそのものの横幅と余白を指定。
開閉動作に影響なし。
*/
.accordion__list {
width: 500px;
padding: 10px;
}
/*
アコーディオンの開閉をつかさどる、
type="checkbox" を指定しているinputタグ。
inputタグそのものは非表示にする。
*/
.accordion__input {
display: none;
}
/*
アコーディオンの2つ目以降、上に余白を取る。
開閉動作に影響なし。
*/
.accordion__item:nth-child(n+2) {
margin-top: 10px;
}
/*
アコーディオンの開閉ボタンの装飾。
position: relative;が無いと、
「+」「-」の位置がずれるので注意。
*/
.accordion__head {
position: relative;
display: block;
width: 100%;
padding: 10px;
color: #fff;
background: #12DE40;
cursor: pointer;
}
/*
アコーディオンの開閉ボタンの右側に「+」を表示。
*/
.accordion__head::after {
content: "+";
position: absolute;
top: 8px;
right: 10px;
}
/*
アコーディオンの閉じている部分の装飾。
height: 0; overflow: hidden;にすることで、
通常時は表示されないようにする。
*/
.accordion__body {
overflow: hidden;
width: 100%;
height: 0;
padding: 0 10px;
background: #e8e8e8;
transition: all .25s ease;
}
/*
アコーディオンの開閉ボタン(labelタグ、class="accordion__head")をクリックすると、
対となっているinputタグ(class="accordion__input")がチェック状態(checked)になる。
チェック状態のinputタグの隣の隣にある、
アコーディオンの閉じている部分(class="accordion__body")の
heightとpaddingを変更し、アコーディオンを開いた状態にする。
*/
.accordion__input:checked + .accordion__head + .accordion__body {
height: auto;
padding: 10px;
}
/*
チェック状態のinputタグの隣にある、開閉ボタンの「+」を「-」に変更する。
*/
.accordion__input:checked + .accordion__head::after
{
content: "-";
right: 13px;
}
最後に
このぐらいシンプルなアコーディオンパネルだと、CSSオンリーでも遜色のない動きを実現できることがわかりました。
リッチな動きが不要なときは、ドンドン使っていこうと思います!