DEV Community

Bruno Vieira
Bruno Vieira

Posted on

20 3

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.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

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

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

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more