How to write jQuery slideUp() and slideDown() in vanilla JS
Before the rise of React and Vue, it was common to use jQuery to write JavaScript on websites. Back then, the slideUp() and slideDown() were one of my favorites. But how to implement them with vanilla JS?
Using CSS transitions
The easiest way is to change the height between 0
and auto
and simply apply CSS transition height.
Here is an example:
<html>
<head>
<style>
.toggleBox {
// Transition property creates the
// "slide animation" effect
// when height changes
transition: height .5s ease;
// overflow:hidden makes sure we don't
// see the content when height is 0
overflow: hidden;
// hide box by default
height: 0;
display: none;
}
</style>
</head>
<body>
<div class="toggleBox" id='toggle-box'>
Box with content of undefined height.
</div>
<button onclick="slideToggle('toggle-box')" >
Slide Toggle
</button>
<script>
function slideToggle(id) {
const container = document.getElementById(id);
const active = container.style.height !== ''
&& container.style.height !== '0px';
// If the height is set, just change in to 0
// CSS transition does the animation job.
if(active){
container.style.height = "0px"
// after CSS transition, change display no none.
// We need to wait for the transition, otherwise
// no transition would happen.
container.addEventListener('transitionend', () => {
container.style.display = 'none';
}, {once: true})
return;
}
// make div visible again
container.style.display = 'block';
// if height is 0, get current height in pixel
container.style.height = "auto"
const height = container.clientHeight + "px"
// set height back to 0
container.style.height = "0px"
// we can't just assign height back to `height`,
// because then the height would never change
// and CSS transition does not come into play
// we need some kind of delay, and this is the
// shortest we can do. Its **magic**
//
// We cannot use 'auto' here, as this would not
// trigger CSS transitions.
setTimeout(() => {
container.style.height = height
}, 0)
// After transition happened, we change height from
// fixed height to auto, so its responsive on window
// change.
container.addEventListener('transitionend', () => {
container.style.display = 'auto';
}, {once: true})
})
</script>
</body>
</html>