Edited at

jQuery非依存のアコーディオン作ってみた

jQueryのslideToggle()はすごく便利ですが、頼りすぎるとエンジニア強度が下がってしまいます。

下がらないように、素のJavaScriptでも、アコーディオンを作ってみましょう。


サンプルコード

こんな感じで作ってみました。


JavaScript

const accordion = (

// 初期値
{
target = 'js-ac',
btn = 'js-ac_btn',
content = 'js-ac_content',
speed = 1.5,
cssEase = 'ease-out'
} = {}
) => {
const TARGET = document.getElementsByClassName(target);
const TARGET_LENGTH = TARGET.length;
for (let i = 0; i < TARGET_LENGTH; i++) {
let isShow = false;
const CURRENT_TARGET = TARGET[i];
const BTN = CURRENT_TARGET.getElementsByClassName(btn)[0];
const CONTENT = CURRENT_TARGET.getElementsByClassName(content)[0];
const MAX_HEIGHT = CONTENT.scrollHeight;
const DURATION = MAX_HEIGHT * speed;
CONTENT.style.transitionDuration = `${DURATION}ms`;
CONTENT.style.transitionTimingFunction = cssEase;
BTN.addEventListener('click', () => {
CONTENT.style.height = isShow ? 0 : `${MAX_HEIGHT}px`;
isShow = !isShow;
});
}
};

// 実行
accordion({
// 初期値の上書き
speed: 1, // 1で100px 100msのスピード
cssEase: 'ease'
});

// 上書きなしで実行
// accordion();



HTML


<div class="js-ac">
<button class="js-ac_btn" type="button">ボタン</button>
<div class="js-ac_content">
<!-- コンテンツ -->
</div>
</div>


CSS


.js-ac {
overflow: hidden;
}
.js-ac_content {
height: 0;
transition-property: height;
}

引数で初期値を上書きすることにより、CSSクラス名やイージング、スピードを調整できます。

では、それぞれの役割をみていきましょう。


解説


引数


JavaScript

// 初期値

{
target = 'js-ac',
btn = 'js-ac_btn',
content = 'js-ac_content',
speed = 1.5,
cssEase = 'ease-out'
} = {}

仮引数部分は、オブジェクトの分割代入を利用して初期値を設定しています。実行時、実引数にオブジェクト形式で記述することにより、初期値を上書きすることができます。

詳しい解説は、こちらをどうぞ。

【JavaScript】関数の引数をオブジェクト形式にして、さらに初期値を設定する。


アコーディオン


JavaScript

// .js-acを取得

const TARGET = document.getElementsByClassName(target);

// .js-acの数だけループ処理
const TARGET_LENGTH = TARGET.length;
for (let i = 0; i < TARGET_LENGTH; i++) {
let isShow = false; // アコーディオンの開閉フラグ
const CURRENT_TARGET = TARGET[i]; // 対象の.js-acクラス
const BTN = CURRENT_TARGET.getElementsByClassName(btn)[0]; // 対象の.js-acクラス内のボタン要素
const CONTENT = CURRENT_TARGET.getElementsByClassName(content)[0]; // 対象の.js-acクラス内の開閉する要素
const MAX_HEIGHT = CONTENT.scrollHeight; // 対象の.js-acクラス内の開閉する要素の高さ
const DURATION = MAX_HEIGHT * speed; // 開閉スピード
CONTENT.style.transitionDuration = `${DURATION}ms`; // transition-durationを設定
CONTENT.style.transitionTimingFunction = cssEase; // transition-timing-functionを設定

// ボタンがクリックされるたびに、開閉する要素の高さと開閉フラグをトグル
BTN.addEventListener('click', () => {
CONTENT.style.height = isShow ? 0 : `${MAX_HEIGHT}px`;
isShow = !isShow;
});
}


scrollHeight()メソットを使うと、要素のもともとの高さを取得できるので、CSSで対象の要素を予めheight: 0;にしておけば、CSS Transitionで開閉をスムーズにアニメーションさせることができます。

また、const DURATION = MAX_HEIGHT * speed;とすることにより、開閉する要素の高さが違っても、同じようなスピード感で開閉できるようにしています。


実行


JavaScript

// 実行

accordion({
// 初期値の上書き
speed: 1, // 1で100px 100msのスピード
cssEase: 'ease'
});

// 上書きなしで実行
// accordion();


実引数で、初期値を上書きすることができます。オブジェクト形式で書くので、見やすいです。


コードペン

See the Pen No jQuery Accordion by Otsuka Yuhi (@boltkeep) on CodePen.

以上!