S
SolidJS17mo ago
Razboy20

CSS Transition does not get animated properly when applied in style={} directly

I have a navbar which I have animated (attached), however to achieve this effect I needed to go in a roundabout way. Basically, the transition needs to switch directions based on which path the user is navigating to, and the issue is that if I compute the transition in the style prop of the div, then the transition updates only after the transition has occurred, rather than influencing the transition. To solve this, I have an effect that sets the style programmatically before the signals are flushed, causing the transition to animate properly.
createEffect<number>((prevIndex) => {
setIndicatorDirection(
(prevIndex ?? getPathIndex()) < getPathIndex()
? Direction.RIGHT
: Direction.LEFT
);

const el = indicatorEl();
if (!el) throw new Error();

// Question here: Can this be moved into the style instead of within an effect?
el.style.transition = `left 350ms ${
indicatorDirection() === Direction.LEFT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
},right 350ms ${
indicatorDirection() === Direction.RIGHT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
}`;

return getPathIndex();
});
createEffect<number>((prevIndex) => {
setIndicatorDirection(
(prevIndex ?? getPathIndex()) < getPathIndex()
? Direction.RIGHT
: Direction.LEFT
);

const el = indicatorEl();
if (!el) throw new Error();

// Question here: Can this be moved into the style instead of within an effect?
el.style.transition = `left 350ms ${
indicatorDirection() === Direction.LEFT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
},right 350ms ${
indicatorDirection() === Direction.RIGHT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
}`;

return getPathIndex();
});
Having a style applied as such:
<div
ref={setIndicatorEl}
style={{
left: `${offsetLeft}px`,
right: `${offsetRight}px`,
transition: `left 350ms ${
indicatorDirection() === Direction.LEFT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
},right 350ms ${
indicatorDirection() === Direction.RIGHT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
}`,
}}
></div>
<div
ref={setIndicatorEl}
style={{
left: `${offsetLeft}px`,
right: `${offsetRight}px`,
transition: `left 350ms ${
indicatorDirection() === Direction.LEFT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
},right 350ms ${
indicatorDirection() === Direction.RIGHT
? 'cubic-bezier(1,0,.3,1) -140ms'
: 'cubic-bezier(.75,0,.24,1) -40ms'
}`,
}}
></div>
does not work. I'm wondering whether there is a better solution to this problem, and whether I am missing a proper method to deal with this sort of issue. You can view a running copy here: https://stackblitz.com/edit/solid-start-latest-g8yyym?file=src%2Fcomponents%2FNavbar.tsx Thanks in advance!
Razboy20
StackBlitz
Navbar Transitions - StackBlitz
Vite + solid-start template
4 Replies
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Razboy20
Razboy2016mo ago
No, those are fine. Those just transition the animation faster.
Unknown User
Unknown User16mo ago
Message Not Public
Sign In & Join Server To View
Razboy20
Razboy2016mo ago
Yeah I agree-that's why applying the transition styles in the effect works-it's applied before the dom is mutated by solid