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
 
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
 
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
 
mooksz profile image
mooksz

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

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
 
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