I got a button styled with Tailwind and Vue js 3. This button contains a classic "Login" text. I want to achieve that when the user clicks and a loading status is triggered, the button shrinks, the "Login" text goes away and a spinner shows.
I achieved most of this, but the smooth shrinking animation. I saw several posts here related, but all talk about animating the width from specific sizes, example: w-32 to w-64, etc.
My button goes from "w-full"(100%) to "w-fit"(the space needed for the spinner to show up). All the animations but width works perfectly fine. Below my sample code.
<button
:class="`bg-red text-white rounded-full transition-all duration-300 ease-in ${
loadingLogin ? 'w-fit' : 'w-full'
}`">
<span v-if="!loadingLogin">Login</span>
<spinner-icon v-else />
</button>
The width
property is currently unable to animate dynamic values, so it cannot transition to w-fit
or w-auto
.
But you can avoid this problem in your case. You can achieve this effect by transitioning flex-grow
. Set it to flex-grow: 1
when you need the element to fill the container, and flex-grow: 0
when it doesn't. Since the element is in a flex
container, its width will also be similar to w-fit
.
<!-- hover to see transition -->
<div class="group/btns flex justify-center">
<button class="grow rounded-full bg-red-500 px-4 py-1 text-white transition-all duration-300 ease-in group-hover/btns:grow-0">
<span class="group-hover/btns:hidden">Login Button</span>
<i class="hidden group-hover/btns:inline">(icon)</i>
</button>
</div>
DEMO on Tailwind Play.
The animation is triggered by hovering in my example. In your real application you can specify the value of flex-grow
based on the loadingLogin
variable.