DEV Community

Bruno Vieira
Bruno Vieira

Posted on

Vanilla JS SlideDown/Up

Hey Guys,

For the past years i've been working with JQuery alot, because it allow do things really fast and has full support in most browsers.

Although it is a lightweight library, it may be too much for what we want to achieve.

Couple days ago i published a way of doing FadeIn/Out in pure javascript, this time, im going to show how to make SlideDown/Up.

Let's get started.


    /* SLIDE UP */
    let slideUp = (target, duration=500) => {

        target.style.transitionProperty = 'height, margin, padding';
        target.style.transitionDuration = duration + 'ms';
        target.style.boxSizing = 'border-box';
        target.style.height = target.offsetHeight + 'px';
        target.offsetHeight;
        target.style.overflow = 'hidden';
        target.style.height = 0;
        target.style.paddingTop = 0;
        target.style.paddingBottom = 0;
        target.style.marginTop = 0;
        target.style.marginBottom = 0;
        window.setTimeout( () => {
              target.style.display = 'none';
              target.style.removeProperty('height');
              target.style.removeProperty('padding-top');
              target.style.removeProperty('padding-bottom');
              target.style.removeProperty('margin-top');
              target.style.removeProperty('margin-bottom');
              target.style.removeProperty('overflow');
              target.style.removeProperty('transition-duration');
              target.style.removeProperty('transition-property');
              //alert("!");
        }, duration);
    }

    /* SLIDE DOWN */
    let slideDown = (target, duration=500) => {

        target.style.removeProperty('display');
        let display = window.getComputedStyle(target).display;
        if (display === 'none') display = 'block';
        target.style.display = display;
        let height = target.offsetHeight;
        target.style.overflow = 'hidden';
        target.style.height = 0;
        target.style.paddingTop = 0;
        target.style.paddingBottom = 0;
        target.style.marginTop = 0;
        target.style.marginBottom = 0;
        target.offsetHeight;
        target.style.boxSizing = 'border-box';
        target.style.transitionProperty = "height, margin, padding";
        target.style.transitionDuration = duration + 'ms';
        target.style.height = height + 'px';
        target.style.removeProperty('padding-top');
        target.style.removeProperty('padding-bottom');
        target.style.removeProperty('margin-top');
        target.style.removeProperty('margin-bottom');
        window.setTimeout( () => {
          target.style.removeProperty('height');
          target.style.removeProperty('overflow');
          target.style.removeProperty('transition-duration');
          target.style.removeProperty('transition-property');
        }, duration);
    }

    /* TOOGLE */
    var slideToggle = (target, duration = 500) => {
        if (window.getComputedStyle(target).display === 'none') {
          return slideDown(target, duration);
        } else {
          return slideUp(target, duration);
        }
    }
Enter fullscreen mode Exit fullscreen mode

That's it, now you can use it like this:


// Specify Element and Duration (milliseconds)
slideUp(document.getElementById("target"), 1000);

slideDown(document.getElementById("target"), 1000);

slideToggle(document.getElementById("target"), 1000);

Enter fullscreen mode Exit fullscreen mode

I found this code online a few days ago and it works well, I hope it helps someone.

Take a look at my most recent project: VanillaJS Fully Customizable SelectBoxes

Thank you.

Top comments (12)

Collapse
 
kartofelek007 profile image
kartofelek007

with and without box-sizing:

let slideUp = (target, duration=500) => {
    target.style.transitionProperty = 'height, margin, padding';
    target.style.transitionDuration = duration + 'ms';
    const computed = getComputedStyle(target);
    if (computed.boxSizing === "border-box") {
        target.style.height = target.offsetHeight + 'px';
    } else {
        const pt = parseFloat(computed.paddingTop);
        const pb = parseFloat(computed.paddingBottom);
        const bt = parseFloat(computed.borderTopWidth);
        const bb = parseFloat(computed.borderBottomWidth);
        target.style.height = target.offsetHeight - pt - pb - bt - bb + 'px';
    }
....
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kabirpathak profile image
Kabir Pathak

Hi Bruno. Can you please explain what the purpose of this line of code is?
target.offsetHeight;
When i remove this from my code, the animation does not work. But this line keeps throwing a linting warning.

Collapse
 
jchibbard profile image
James Hibbard

This line forces the browser to restart a CSS animation.
Explanation here: css-tricks.com/restart-css-animation/
Further discussion here: sitepoint.com/community/t/why-does...

Collapse
 
sysmaya profile image
sysmaya

I like it. But I prefer to add it as prototype, so I call the function "natively"

Element.prototype.slideUp= function ( duration) {
// Slide code
};

element.slideUp(500);
Enter fullscreen mode Exit fullscreen mode
Collapse
 
spamator12 profile image
spamator12

Does not work when you want slide multiple elements at once via querySelectionAll or for example
var list = document.getElementsByClassName("class1", "class2", "class3");

slideUp(list, 500); // error target.style relate to multiple elements...

Collapse
 
mooksz profile image
mooksz

This throws an error for me: error Expected an assignment or function call and instead saw an expression.

Its related to the lines:
target.offsetHeight;
target.offsetHeight;

Collapse
 
mooksz profile image
mooksz

Ah just relized its a bad copy from: w3bits.com/javascript-slidetoggle/

Collapse
 
jchibbard profile image
James Hibbard • Edited

Might be because you are running in strict mode?
Try changing to void target.offsetHeight; see if that helps.
Ref.: css-tricks.com/restart-css-animation/

Collapse
 
pyrobri profile image
Brian

adding void just creates another linting issue asking to:
Remove this use of the "void" operator. (javascript:S3735)

Collapse
 
notrealdev profile image
notrealdev

Thank Bruno :D

Collapse
 
vasylkyrtyanyk profile image
Vasyl Kurtyanik

Hi, when I use these methods I also need to use the "stop" method from Jquery.
Because we need to stop our animation. Could you help me with it?

Collapse
 
bmsvieira profile image
Bruno Vieira

Hello,

Sure, i have to do some research but probably you can use:

var element =  document.getElementById(selector);
element.webkitAnimationPlayState = 'paused';
Enter fullscreen mode Exit fullscreen mode