【jQueryを完全再現】slideUp, slideDown, slideToggleを素のJavaScriptで実装する方法

jQueryにはslideUp(),slideDown(), slideToggle()といったメソッドがあります。

これらを使用すると、少ないコードで要素をスライドしつつ表示/非表示にできるので、すごく便利ですね。

しかし案件によっては、jQueryを使いたくない場合があるかと思います。

そこで今回の記事では、jQueryのslide系メソッドをJavaScriptで実装する方法を紹介します!

「jQueryを読み込みたくないけど、slide系のメソッドは使用したい」という方は、ぜひ使ってみてください。

目次

【JSとjQueryの比較】slideUp, slideDown, slideToggleのDEMO

以下にJavaScriptとjQueryで実装したDEMOを用意しました。

DEMOには以下の3つの機能を持つボタンを実装しています。

  • slideUp…要素をスライドしながら隠す
  • slideDown…要素をスライドしながら表示する
  • slideToggleslideUpslideDownを交互に切り替える

まずは実際の挙動を確認してみてください。

JavaScriptで実装した場合のDEMO

こちらはJavaScriptでslideUp・slideDown・slideToggleを実装したDEMOです。

それぞれのボタンをクリックして、動作を確認してみてください。

Vanilla JavaScriptで実装した
slideUp / slideDown / slideToggleのDEMO

jQueryで実装した場合のDEMO

続いてはjQueryのslideUp・slideDown・slideToggleを使用したDEMOです。

jQueryには、これらのメソッドがはじめから用意されていますね。

jQueryで実装した
slideUp / slideDown / slideToggleのDEMO

【比較した結果】JavaScriptでjQueryのslide系メソッドを再現可能!

2つのDEMOを確認していただくとわかると思いますが、JavaScriptでjQueryのslide系メソッドを再現できていますね。

そもそもjQueryはJavaScriptで構成されたライブラリなので、当然素のJavaScriptでも実装することができます!

次で実際のJavaScriptのコードを見ていきましょう。

【コピペ用】slideUp, slideDown, slideToggleの実装JSコード

以下がJavaScriptで実装したslideUp, slideDown, slideToggleの3つの関数のコードです。

// slideUp
const slideUp = (el, duration = 300) => {
  el.style.height = el.offsetHeight + "px";
  el.offsetHeight;
  el.style.transitionProperty = "height, margin, padding";
  el.style.transitionDuration = duration + "ms";
  el.style.transitionTimingFunction = "ease";
  el.style.overflow = "hidden";
  el.style.height = 0;
  el.style.paddingTop = 0;
  el.style.paddingBottom = 0;
  el.style.marginTop = 0;
  el.style.marginBottom = 0;
  setTimeout(() => {
    el.style.display = "none";
    el.style.removeProperty("height");
    el.style.removeProperty("padding-top");
    el.style.removeProperty("padding-bottom");
    el.style.removeProperty("margin-top");
    el.style.removeProperty("margin-bottom");
    el.style.removeProperty("overflow");
    el.style.removeProperty("transition-duration");
    el.style.removeProperty("transition-property");
    el.style.removeProperty("transition-timing-function");
  }, duration);
};

// slideDown
const slideDown = (el, duration = 300) => {
  el.style.removeProperty("display");
  let display = window.getComputedStyle(el).display;
  if (display === "none") {
    display = "block";
  }
  el.style.display = display;
  let height = el.offsetHeight;
  el.style.overflow = "hidden";
  el.style.height = 0;
  el.style.paddingTop = 0;
  el.style.paddingBottom = 0;
  el.style.marginTop = 0;
  el.style.marginBottom = 0;
  el.offsetHeight;
  el.style.transitionProperty = "height, margin, padding";
  el.style.transitionDuration = duration + "ms";
  el.style.transitionTimingFunction = "ease";
  el.style.height = height + "px";
  el.style.removeProperty("padding-top");
  el.style.removeProperty("padding-bottom");
  el.style.removeProperty("margin-top");
  el.style.removeProperty("margin-bottom");
  setTimeout(() => {
    el.style.removeProperty("height");
    el.style.removeProperty("overflow");
    el.style.removeProperty("transition-duration");
    el.style.removeProperty("transition-property");
    el.style.removeProperty("transition-timing-function");
  }, duration);
};

// slideToggle
const slideToggle = (el, duration = 300) => {
  if (window.getComputedStyle(el).display === "none") {
    return slideDown(el, duration);
  } else {
    return slideUp(el, duration);
  }
};

これらを使用する場合は、以下のように記述します。

// スライドさせたい要素を取得
const el = document.querySelector('.element');
// ボタン
const slideUpBtn = document.querySelector(".slide-up-btn");
const slideDownBtn = document.querySelector(".slide-down-btn");
const slideToggleBtn = document.querySelector(".slide-toggle-btn");

// slideUp
slideUpBtn.addEventListener("click", () => {
  slideUp(el, 300);
});

// slideDown
slideDownBtn.addEventListener("click", () => {
  slideDown(el, 300);
});

// slideToggle
slideToggleBtn.addEventListener("click", () => {
  slideToggle(el, 300);
});

slideUp, slideDown, slideToggleの関数には、それぞれ2つの引数を指定できます。

  • 第一引数:ターゲット要素
  • 第二引数:アニメーションの実行時間(ms)

第一引数には、スライドしながら表示/非表示させるターゲット要素を指定します。

第二引数には、アニメーションの実行時間をミリ秒単位で指定できます。こちらにはデフォルト引数を設定しているので、空白の場合はデフォルト値が適用されるようになっています。

これでJSコードの全体像が確認できました。

次からは、それぞれの関数の解説をしていきます。

【解説】slideUp, slideDown, slideToggleのJSコード解説

ここからは、slideUp, slideDown, slideToggleの実装コードを順番に解説していきます!

コードを理解したいという方は、ぜひ読んでみてください。

slideUpの解説

まずはslideUpから説明していきます。

slideUpは、要素をスライドしながら非表示にすることができます。

以下のDEMOでもう一度確認してみてください。

Vanilla JavaScriptで実装した
slideUp / slideDown / slideToggleのDEMO

要素が上にスライドしながら隠れるのが確認できたかと思います!

以下でslideUpの実際のコードをみていきましょう。

// slideUp
const slideUp = (el, duration = 300) => {
  el.style.height = el.offsetHeight + "px";
  el.offsetHeight;
  el.style.transitionProperty = "height, margin, padding";
  el.style.transitionDuration = duration + "ms";
  el.style.transitionTimingFunction = "ease";
  el.style.overflow = "hidden";
  el.style.height = 0;
  el.style.paddingTop = 0;
  el.style.paddingBottom = 0;
  el.style.marginTop = 0;
  el.style.marginBottom = 0;
  setTimeout(() => {
    el.style.display = "none";
    el.style.removeProperty("height");
    el.style.removeProperty("padding-top");
    el.style.removeProperty("padding-bottom");
    el.style.removeProperty("margin-top");
    el.style.removeProperty("margin-bottom");
    el.style.removeProperty("overflow");
    el.style.removeProperty("transition-duration");
    el.style.removeProperty("transition-property");
    el.style.removeProperty("transition-timing-function");
  }, duration);
};

こちらがslideUpの全体像ですね。

分解しつつ説明していきます。

/* ① */
el.style.height = el.offsetHeight + "px";
el.offsetHeight;
/* ② */
el.style.transitionProperty = "height, margin, padding";
/* ③ */
el.style.transitionDuration = duration + "ms";
/* ④ */
el.style.transitionTimingFunction = "ease";
/* ⑤ */
el.style.overflow = "hidden";
  1. ターゲット要素のスタイル属性にheightを設定。値にはoffsetHeightで取得したターゲット要素の高さが入る。
  2. transitionを適用するプロパティを指定。ここではheight, margin, paddingを徐々に変化させたいので、これらを指定。
  3. transitionの実行時間を指定。引数として設定したdurationの値が入る。
  4. transitionのタイミング関数を指定。アニメーションの進行具合を調整できる。値にはease-in, ease-out, linearなどを指定可能。
  5. 要素がはみ出した場合、その部分を非表示にするoverflow: hiddenを指定。
/* ⑥ */
el.style.height = 0;
el.style.paddingTop = 0;
el.style.paddingBottom = 0;
el.style.marginTop = 0;
el.style.marginBottom = 0;
  1. height, padding-top, padding-bottom, margin-top, margin-bottomの値を0にする。

②の時点でheight, padding, margintransitionがかかるよう指定しているので、この時点で要素の高さが徐々に小さくなっていき、最終的には0になります。

setTimeout(() => {
  /* ⑦ */
  el.style.display = "none";
  /* ⑧ */
  el.style.removeProperty("height");
  el.style.removeProperty("padding-top");
  el.style.removeProperty("padding-bottom");
  el.style.removeProperty("margin-top");
  el.style.removeProperty("margin-bottom");
  el.style.removeProperty("overflow");
  el.style.removeProperty("transition-duration");
  el.style.removeProperty("transition-property");
  el.style.removeProperty("transition-timing-function");
}, duration);

ここではsetTimeoutを使用して、アニメーション完了後の指定をします。

  1. display: noneを指定して要素を非表示にする。
  2. アニメーション完了後、必要なくなったプロパティを一斉に削除。

以上でslideUpの解説は終わりです!

slideDownの解説

続いてはslideDownを解説していきます。

slideDownは、要素をスライドしながら表示することができる関数ですね。

以下のDEMOで動作確認してみてください。

Vanilla JavaScriptで実装した
slideUp / slideDown / slideToggleのDEMO

要素が下にスライドしつつ、徐々に表示されるアニメーションが確認できたかと思います。

以下でslideDownの実際のコードをみていきましょう。

// slideDown
const slideDown = (el, duration = 300) => {
  el.style.removeProperty("display");
  let display = window.getComputedStyle(el).display;
  if (display === "none") {
    display = "block";
  }
  el.style.display = display;
  let height = el.offsetHeight;
  el.style.height = 0;
  el.style.paddingTop = 0;
  el.style.paddingBottom = 0;
  el.style.marginTop = 0;
  el.style.marginBottom = 0;
  el.offsetHeight;
  el.style.transitionProperty = "height, margin, padding";
  el.style.transitionDuration = duration + "ms";
  el.style.transitionTimingFunction = "ease";
  el.style.overflow = "hidden";
  el.style.height = height + "px";
  el.style.removeProperty("padding-top");
  el.style.removeProperty("padding-bottom");
  el.style.removeProperty("margin-top");
  el.style.removeProperty("margin-bottom");
  setTimeout(() => {
    el.style.removeProperty("height");
    el.style.removeProperty("overflow");
    el.style.removeProperty("transition-duration");
    el.style.removeProperty("transition-property");
    el.style.removeProperty("transition-timing-function");
  }, duration);
};

slideDownの実装コードは以上です。

先ほど説明したslideUpのコードとの共通点が多めですね。

/* ① */
el.style.removeProperty("display");
/* ② */
let display = window.getComputedStyle(el).display;
/* ③ */
if (display === "none") {
  display = "block";
}
/* ④ */
el.style.display = display;
  1. ターゲット要素のstyle属性にdisplayが設定されている場合、削除。
  2. ターゲット要素のdisplayプロパティの値を取得し、変数displayに値を格納。
  3. もしターゲット要素にdisplay: noneが設定されている場合、blockを指定。
  4. ②で変数displayに格納した値を、style属性のdisplayの値に設定。

ここは一見ややこしく見えますが、

  • 要素のdisplayの値がnoneの場合…blockを指定する
  • 要素のdisplayの値がnone以外の場合…CSSで指定されている値をそのまま指定する

という処理を行なっています。

slideDownは要素を表示する役割を持つので、displayの値はnone以外にする必要がありますよね。

この記述をすることでblock, inline-block, flexなど、ターゲットにどのプロパティが設定されていても柔軟に対応することができます。

/* ⑤ */
let height = el.offsetHeight;
/* ⑥ */
el.style.height = 0;
el.style.paddingTop = 0;
el.style.paddingBottom = 0;
el.style.marginTop = 0;
el.style.marginBottom = 0;
  1. 変数heightにターゲット要素の高さを格納。
  2. height, 上下padding, 上下margin0にしてstyle属性に設定。
/* ⑦ */
el.style.transitionProperty = "height, margin, padding";
el.style.transitionDuration = duration + "ms";
el.style.transitionTimingFunction = "ease";
/* ⑧ */
el.style.overflow = "hidden";
  1. transition-property,transition-duration ,transition-timing-functionをそれぞれ設定。
  2. 親要素からはみ出す部分を非表示にするoverflow: hiddenを指定。
/* ⑨ */
el.style.height = height + "px";
/* ⑩ */
el.style.removeProperty("padding-top");
el.style.removeProperty("padding-bottom");
el.style.removeProperty("margin-top");
el.style.removeProperty("margin-bottom");
  1. ⑤で取得した高さをstyle属性のheightに設定。
  2. padding, marginの上下の値をstyle属性から取り除く。

ステップ⑥で、height, 上下padding, 上下marginの値を0にしましたね。

ステップ⑨⑩では、0にしたそれぞれの値をもとの数値に戻していきます。

まず⑤で取得した要素の高さを、style属性のheightに指定します。

これで要素が持つ本来の高さを指定できました。

次に、0を指定していた上下padding, marginをstyle属性から取り除きます。

これでCSSに指定したpaddingmarginが適用されるようになり、要素を元通りにすることができました。

setTimeout(() => {
  /* (11) */
  el.style.removeProperty("height");
  el.style.removeProperty("overflow");
  el.style.removeProperty("transition-duration");
  el.style.removeProperty("transition-property");
  el.style.removeProperty("transition-timing-function");
}, duration);
  1. アニメーション完了後、必要なくなったプロパティを一斉に削除。

アニメーション完了後、いらなくなったプロパティをstyle属性から取り除きます。

これでslideDownの解説は終わりです!

slideToggleの解説

最後にslideToggleの解説をしていきます。

slideToggleは、要素が隠れている場合はスライドしながら表示表示されている場合はスライドしながら非表示にする関数です。

まずはDEMOで動きを再確認しておきましょう。

Vanilla JavaScriptで実装した
slideUp / slideDown / slideToggleのDEMO

要素がスライドしながら表示/非表示を交互に切り替えるアニメーションが確認できたかと思います。

以下がslideToggleの実装コードです。

const slideToggle = (el, duration = 300) => {
  /* ① */
  if (window.getComputedStyle(el).display === "none") {
    /* ② */
    return slideDown(el, duration);
  } else {
    /* ③ */
    return slideUp(el, duration);
  }
};
  1. 要素のdisplayプロパティの値がnoneかどうかを判定。
  2. noneの場合 = slideDown関数を返して要素を表示する。
  3. none以外の場合 = slideUp関数を返して要素を隠す。

ここではまずクリックした段階で要素が表示されているかどうかを判別します。

もしdisplayの値がnoneの場合、要素は非表示であるという意味になりますね。

その場合はslideDown関数を返して要素を表示します。

反対に、displayの値がnone以外の場合は、要素は表示されている状態なので、slideUp関数を返して要素を隠します。

これでslideToggleの解説は終わりです!

【まとめ】jQueryのslide系メソッドは素のJavaScriptで実装可能!

今回の記事では、jQueryのslideUp, slideDown, slideToggleメソッドを素のJavaScriptで実装する方法を紹介しました。

jQueryは便利なライブラリですが、使用したくない場面もあるかと思います。

そういった場合は、今回紹介したコードをぜひ使ってみてください!

Web制作に関する
記事案を募集中!

Web制作について知りたいこと、質問等ありましたら、以下のフォームから気軽に投稿してください。
要望が多かったものは解説記事を作成します。

よかったらシェアしてね!

コメント

コメント一覧 (2件)

  • 不明点がありましたのでご質問させて頂ければと存じます。

    Slide Downのコードでel.style.removeProperty(“display”);の表記がございますが、
    こちら必要でしょうか?
    noneとblockの付け外しのみで良いような気がしたのですが、特別に記載している理由があれば
    ご教示頂けたら幸いです。

    // slideDown
    const slideDown = (el, duration = 300) => {
    el.style.removeProperty(“display”);
    let display = window.getComputedStyle(el).display;
    if (display === “none”) {
    display = “block”;

    宜しくお願い致します。

  • コメントありがとうございます!
    おっしゃる通りで、もし’block’と’none’を切り替えたい場合はremovePropertyの記述は必要ありません。
    しかし、’block’以外の値(例えば’flex’や’inline-block’など)にも対応したい場合は、必要になります。

    以下で、’flex’と’none’を切り替えたい場合について説明しますね。
    前提として、CSSは以下のようになっています。

    ○CSS
    .element {
    display: flex;
    }
    ————————
    ■el.style.removeProperty(“display”);の記述がある場合
    el.style.removeProperty(“display”); // 要素のstyleから’display:none’を削除
    let display = window.getComputedStyle(el).display; // 要素のdisplayの値を取得(’flex’)
    if (display === “none”) { // 変数displayには’flex’が入っているため{}内は適用されない
    display = “block”;
    }
    el.style.display = display; // displayには’flex’が指定される

    ■el.style.removeProperty(“display”);の記述がない場合
    let display = window.getComputedStyle(el).display; // 変数displayには、style属性の’none’が格納される(CSSの’display: flex’よりもスタイル属性が優先されるため)
    if (display === “none”) { // 変数displayには’none’が入っているため{}内を適用(デフォルト値の’block’が指定される)
    display = “block”;
    }
    el.style.display = display; // displayには’block’が指定される
    ————————

    分かりづらい説明で申し訳ないです・・。
    簡潔に言うと、removePropertyの行を記述しないと、CSS側で’flex’や’inline-block’を指定しても、slideDownを使用すると’block’になってしまうということです。
    一度自身のコードで試していただくと、理解しやすいかと思います!

Tatsuya へ返信する コメントをキャンセル

目次
閉じる