Alpine.js Transition Shortcuts You Won't Find in the Docs

/ Content

Quick tip that I keep forgetting exists: Alpine's x-transition has .in and .out modifiers that aren't in the documentation.

The Problem

You're building tabs. Each tab panel uses x-show with x-transition for a nice fade effect:

<div x-data="{ tab: 'one' }">
    <button @click="tab = 'one'">Tab One</button>
    <button @click="tab = 'two'">Tab Two</button>
    
    <div x-show="tab === 'one'" x-transition>
        Content for tab one
    </div>
    <div x-show="tab === 'two'" x-transition>
        Content for tab two
    </div>
</div>

Click between tabs and watch the jank. The outgoing tab fades out while the incoming tab fades in, causing the content to jump around. Both panels briefly exist in the DOM during the transition, stacking on top of each other or pushing content around.

There are CSS fixes for this. You can position the panels absolutely so they overlap. You can use x-cloak and carefully manage display states. But these add complexity for what should be a simple interaction.

What you actually want is for the outgoing tab to just disappear instantly while the incoming tab fades in smoothly.

The Solution

<div x-show="tab === 'one'" x-transition.in>
    Content for tab one
</div>
<div x-show="tab === 'two'" x-transition.in>
    Content for tab two
</div>

The .in modifier tells Alpine to only apply the transition when the element is entering. When leaving, it just sets display: none immediately. No fade out, no overlap, no jank.

There's also .out if you want the opposite: instant show, animated hide.

The Documented Alternative

You can achieve the same result with x-transition:enter alone:

<div x-show="tab === 'one'" x-transition:enter="transition duration-200">
    Content for tab one
</div>

If you only specify enter transitions without any leave transitions, Alpine won't animate the leave. This is documented behavior, but it's not obvious that omitting leave is intentional and not an oversight.

The .in modifier is more explicit about intent. When someone reads x-transition.in, they know you specifically want enter-only animations. With x-transition:enter alone, it could look like you forgot to add the leave transition.

Chaining Modifiers

Both .in and .out work with other transition modifiers:

<div x-show="open" x-transition.in.duration.500ms.scale.90>

This applies a 500ms enter transition scaling from 90%, with no leave transition.

When to Use This

Tab panels and accordion content are the obvious use cases. Anywhere you have mutually exclusive content that swaps, enter-only transitions prevent the awkward overlap during state changes.

For modals and dropdowns, you usually want both enter and leave animations. The full x-transition or explicit enter/leave classes work better there.

The .in and .out modifiers have been in Alpine's source for years. Maybe they'll make it to the docs eventually, maybe they're intentionally undocumented because the x-transition:enter approach is considered more explicit. Either way, they work and they're useful.