jQueryのslideDown()やslideUp()のような挙動を、VanillaJSで実装してみます。
サンプルコード
slideDown・slideUp・slideToggleの関数を用意します。
/**
* 要素をスライドダウンで表示する
* @param {object} element - 対象要素
* @param {number} speed - スライド速度(ms)
*/
function slideDown(element, speed = 400) {
if(element.classList.contains('is-sliding')) return; // スライド中の場合は処理を行わない
if(window.getComputedStyle(element).display !== 'none') return; // 要素が非表示でない場合は処理を行わない
element.classList.add('is-sliding'); // スライド中判別用のclass追加
// 要素を表示して高さを取得
element.style.removeProperty('display');
const display = window.getComputedStyle(element).display;
if(display === 'none') {
element.style.display = 'block';
}
const height = element.offsetHeight;
// スライド実行前の設定
element.style.overflow = 'hidden';
// 各値にスライド開始時の値を設定
element.style.height = 0;
element.style.paddingTop = 0;
element.style.paddingBottom = 0;
element.style.marginTop = 0;
element.style.marginBottom = 0;
// スライド実行前の設定
setTimeout(function() {
// transitionの設定
element.style.transitionProperty = 'height, margin-top, margin-bottom, padding-top, padding-bottom';
element.style.transitionDuration = `${speed}ms`;
// 各値をスライド終了時の値に変更
element.style.height = `${height}px`;
removeStyleProperties(element, [
'margin-top', 'margin-bottom', 'padding-top', 'padding-bottom'
]);
}, 0);
// スライド実行後の設定
setTimeout(function() {
// style属性内の不要なプロパティを削除
removeStyleProperties(element, [
'height', 'overflow', 'transition-property', 'transition-duration'
]);
element.classList.remove('is-sliding'); // スライド中判別用のclass削除
}, speed);
}
/**
* 要素をスライドアップで非表示にする
* @param {object} element - 対象要素
* @param {number} speed - スライド速度(ms)
*/
function slideUp(element, speed = 400) {
if(element.classList.contains('is-sliding')) return; // スライド中の場合は処理を行わない
if(window.getComputedStyle(element).display === 'none') return; // 要素が非表示の場合は処理を行わない
element.classList.add('is-sliding'); // スライド中判別用のclass追加
// スライド実行前の設定
element.style.overflow = 'hidden';
// スライド開始時の値を設定
element.style.height = `${element.offsetHeight}px`;
// スライド実行前の設定
setTimeout(function() {
// transitionの設定
element.style.transitionProperty = 'height, margin-top, margin-bottom, padding-top, padding-bottom';
element.style.transitionDuration = `${speed}ms`;
// 各値をスライド終了時の値に変更
element.style.height = 0;
element.style.paddingTop = 0;
element.style.paddingBottom = 0;
element.style.marginTop = 0;
element.style.marginBottom = 0;
}, 0);
// スライド実行後の設定
setTimeout(function() {
// 要素を非表示に変更
element.style.display = 'none';
// style属性内の不要なプロパティを削除
removeStyleProperties(element, [
'height', 'overflow', 'transition-property', 'transition-duration',
'margin-top', 'margin-bottom', 'padding-top', 'padding-bottom'
]);
element.classList.remove('is-sliding'); // スライド中判別用のclass削除
}, speed);
}
/**
* 要素の表示状態に応じてslideDown/slideUpの動作を行う
* @param {object} element - 対象要素
* @param {number} speed - スライド速度(ms)
*/
function slideToggle(element, speed = 400) {
// 要素が非表示の場合はslideDownを実行
if(window.getComputedStyle(element).display === 'none') {
slideDown(element, speed);
// 要素が非表示でない場合はslideUpを実行
} else {
slideUp(element, speed);
}
}
/**
* 要素のstyle属性から指定したプロパティを除去する
* @param {object} element - 対象要素
* @param {array} properties - 除去するプロパティ
*/
function removeStyleProperties(element, properties) {
for(const property of properties) {
element.style.removeProperty(property);
}
}
基本的にはコード内に記載しているコメントの通りです。
スライド時はoverflow: hidden を設定した上で、height(+margin・padding)の値を変更してアニメーションを行っています。
jQueryではstyle属性内のheightの値を直接変更してアニメーションを行っていますが、今回のサンプルではtransitionを使ってアニメーションを行うようにしています、
実際に動作を試してみます。
<button id="slideDown">slideDown</button> <button id="slideUp">slideUp</button> <button id="slideToggle">slideToggle</button> <div id="sample"> テストテストテスト<br> テストテストテスト<br> テストテストテスト </div>
各ボタンクリック時に関数を実行するように設定します。
const elem = document.getElementById('sample');
document.getElementById('slideDown').addEventListener('click', function() {
slideDown(elem, 1000);
});
document.getElementById('slideUp').addEventListener('click', function() {
slideUp(elem, 1000);
});
document.getElementById('slideToggle').addEventListener('click', function() {
slideToggle(elem, 1000);
});
これでVanillaJSでスライド系の処理を実装できました。
slideDown・slideUp・slideToggleのデモページ
コメントが承認されるまで時間がかかります。