I'm trying to replicate this effect where the active tab indicator is animated.
My CodeSandbox
Expected behavior: The navlink's highlight should be animated regardless of the flex container's direction.
Current behavior: It only animates when flex-direction
is column
, not row
.
Line 25: Here's the orange highlight:
{hoverAnchor === link && (
<motion.div
layoutId="underline"
transition={{ duration: 0.15 }}
className="absolute bottom-0 left-0 h-[2px] w-full bg-orange"
/>
)}
Line 58: Here's the <motion.ul>
grandparent, which is a flexbox: column when screen size <= 640px, otherwise row:
<motion.ul
initial={{ x: 'var(--menu-offscreen)' }}
animate={{ x: menuOpen ? 0 : 'var(--menu-offscreen)' }}
onMouseLeave={() => setHoverAnchor('')}
className="fixed left-4 top-4 flex h-[calc(100vh_-_2rem)] w-[calc(100vw_-_2rem)] flex-col rounded-lg bg-white py-4 [--menu-offscreen:-400px] xs:max-w-[368px] sm:static sm:h-auto sm:w-auto sm:max-w-full sm:flex-row sm:py-0 sm:outline-none sm:[--menu-offscreen:0px]"
>
It will animate correctly if flex-direction
is column
It will animate correctly if I turn the grandparent <motion.ul>
back into a regular <ul>
, but I don't want to because it has its own animation to do.
Not sure what I'm missing, and the docs doesn't seem to say anything about nesting motion divs, or I couldn't find one.
I tinkered around and found the problem lies in the CSS variables, not <motion.ul>
itself:
<motion.ul
initial={{ x: 'var(--menu-offscreen)' }}
animate={{ x: menuOpen ? 0 : 'var(--menu-offscreen)' }}
className="[--menu-offscreen:-400px] sm:[--menu-offscreen:0px]"
>
I was trying to animate x
based on CSS variable --menu-offscreen
which changes depending on Tailwind's breakpoints. The problem disappears if I don't use var(--menu-offscreen)
in intial
and animate
, so I replace it with a fixed number, and now I handle the breakpoint changes with React instead of Tailwind. It looks something like this:
{/* react state */ smallScreen && (
<motion.ul
initial={{ x: -400 }}
animate={{ x: 0 }}
/>
)}