What the heck is the page? Well fellow traveler, I embarked on a quest for how to animate height and it has taken me many places. This is my log of what I have tried and what the best answer is at the moment
More insights from this journey are here and the github for this code is here
For the sake of example I have chosen an disclosure component to test out different solutions on. You will find it below
boring... :) but works — this is the base component that will be used on the rest of the animations
Framer Motion allows you to animate props from 0
to auto
. This is pretty dope and the simplest way of animating. Unfortunately this actually animating height
in css so watch the perf on this.
(If you want a transform based option scroll down to the layout options)
<AnimatePresence mode="wait">
{isOpen && (
<motion.div
initial={{
height: 0,
opacity: 0,
}}
animate={{
height: "auto",
opacity: 1,
}}
exit={{
height: 0,
opacity: 0,
}}
key="test"
className="text-lg font-light"
>
{props.description}
</motion.div>
)}
</AnimatePresence>
My only gripe the above animation is that the text is cut off by the changing height. This is because text size doesn't shrink based on the height of the element changing. It's size is determined by the font-size
prop, so it just overflows. In our case, this looks bad. I originally solved this with a bunch of big brain ways, but I recently found that Sam Selikoff had a solution that was really simple.source
transition={{
height: {
duration: 0.4,
},
opacity: {
duration: 0.3,
},
}}
Just animate the properties so that the opacity changes sooner than the height. Brilliant!
I got some more feedback and update the article to reflect the accessibility upgrade
From here on you are entering the graveyard of what I have tried. Proceed if you must.
ok, just sucks that there is a _delay_ on the exit
me trying to animate height from 0
to auto
with keyframes (this throws)