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>