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のデモページ
コメントが承認されるまで時間がかかります。