Search code examples
vuejs3tailwind-csscss-transitions

Tailwind width transition for non specific values


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>

Solution

  • 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.