March 30, 2023
Slide up/down animation with AlpineJS
With CSS it is not possible to transition the height
property to auto
:
1.collapsible {2 height: 0;3 overflow: hidden;4 transition: height .3s;5}6 7.collapsible.is-open {8 height: auto;9}
For years developers relied on jQuery's (or Velocity's) slideUp()
and slideDown()
methods to perform slide up/down animations without setting a fixed height. In fact, I remember being brought into projects where jQuery was added to the project just for these 2 methods.
Here is how to implement slide up/down animation with Alpine JS.
Component set up
Start with an Alpine component with a property to manage the open state of a collapsible element. And let's add a .collapsible
element.
1<div x-data="{isOpen: false}">2 <div class="collapsible">3 <!-- your content -->4 </div>5</div>
CSS
Then we add the CSS styles for the collapsed state:
1.collapsible {2 height: 0;3 opacity: 0;4 overflow: hidden;5 transition: all .4s;6 pointer-events: none;7}
And then we add the CSS for the expanded state (excluding the height
which we'll manage with Alpine):
1.collapsible.is-open {2 opacity: 1;3 pointer-events: auto;4}
The magic
What we want to do when the isOpen
property is set to true
:
- Add the
.is-open
class to the.collapsible
element - Programmatically set a
height
to the.collapsible
element
For (1), we'll use x-bind to conditionally set a class based on the value of the isOpen
property. This can be written as x-bind:class
or :class
:
1<div x-data="{isOpen: false}">2 <div3 class="collapsible"4 :class="isOpen && 'is-open'"5 >6 <!-- your content -->7 </div>8</div>
For (2), we'll also use x-bind
, but to add some inline styles. We'll add the height
property and give it a value we calculate with JS.
"Calculate" is a misleading term here. We are going to literally read the height of the element using scrollHeight which includes the height of an element's visible and invisible content. We'll access the element's DOM node using Alpine's $el magic property.
1<div x-data="{isOpen: false}">2 <div3 class="collapsible"4 :class="isOpen && 'is-open'"5 :style="isOpen && {height: $el.scrollHeight+`px`}"6 >7 <!-- your content -->8 </div>9</div>
Here is the full demo including a button to expand/collapse the element:
See the Pen AlpineJS: slide up/down animation by Hussein Al Hammad (@hus_hmd) on CodePen.