Transitions
Tailwind transitions animate property changes — hover effects, theme toggles, accordions. Set transition, choose properties, duration, easing. For complex animation, drop to @keyframes or a library.
Properties, duration, ease, hover
EXAMPLE
<!-- 1) Default transition — most properties, 150ms ease -->
<button class="bg-sky-500 hover:bg-sky-700 text-white px-4 py-2 rounded transition">
Click me
</button>
<!-- 2) Transition specific properties -->
<div class="transition-colors">…</div> <!-- color, bg, border, fill, stroke -->
<div class="transition-opacity">…</div>
<div class="transition-transform">…</div>
<div class="transition-shadow">…</div>
<div class="transition-all">…</div> <!-- everything (perf cost) -->
<div class="transition-none">…</div>
<!-- Specific properties via arbitrary -->
<div class="transition-[height,opacity]">…</div>
<!-- 3) Duration -->
<div class="transition duration-75">…</div> <!-- 75ms -->
<div class="transition duration-150">…</div>
<div class="transition duration-300">…</div> <!-- common default -->
<div class="transition duration-500">…</div>
<div class="transition duration-1000">…</div>
<div class="transition duration-[1500ms]">…</div> <!-- arbitrary -->
<!-- 4) Easing -->
<div class="transition ease-linear">…</div>
<div class="transition ease-in">…</div>
<div class="transition ease-out">…</div> <!-- great for entering elements -->
<div class="transition ease-in-out">…</div>
<div class="transition ease-[cubic-bezier(0.4,0,0.2,1)]">…</div>
<!-- 5) Delay -->
<div class="transition delay-150">…</div>
<div class="transition delay-300">…</div>
<!-- 6) Hover / focus / active patterns -->
<button class="bg-sky-500 hover:bg-sky-700 hover:-translate-y-0.5 hover:shadow-lg transition active:scale-95">
Hover + active feedback
</button>
<!-- 7) Hover scale -->
<img
src="photo.jpg"
class="transition-transform duration-500 hover:scale-110"
/>
<!-- Hover lift -->
<div class="transition-shadow duration-200 hover:shadow-xl">…</div>
<!-- Hover rotate -->
<div class="transition-transform hover:rotate-12">…</div>
<!-- Hover ring -->
<button class="focus:ring-2 focus:ring-sky-500 focus:ring-offset-2 transition">
Focus ring
</button>
<!-- 8) Card hover (combine multiple) -->
<article class="bg-white rounded-lg p-6 shadow transition duration-300 ease-out hover:shadow-2xl hover:-translate-y-1">
<h3>Card title</h3>
<p>Card body</p>
</article>
<!-- 9) Theme toggle — body transitions -->
<body class="bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100 transition-colors duration-200">
…
</body>
<!-- 10) Group hover — parent hover triggers child changes -->
<div class="group p-4 hover:bg-slate-100 transition">
<h3 class="group-hover:text-sky-600 transition-colors">Title</h3>
<p class="group-hover:translate-x-1 transition-transform">Description</p>
<span class="opacity-0 group-hover:opacity-100 transition-opacity">→</span>
</div>
<!-- 11) Peer — sibling state -->
<input type="checkbox" class="peer hidden" id="toggle" />
<label for="toggle" class="cursor-pointer peer-checked:text-sky-600 transition">
Toggle me
</label>
<div class="max-h-0 overflow-hidden peer-checked:max-h-screen transition-all">
Hidden content
</div>
<!-- 12) Accordion / collapse -->
<div x-data="{ open: false }">
<button @@click="open = !open">Toggle</button>
<div
x-show="open"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 -translate-y-2"
x-transition:enter-end="opacity-100 translate-y-0"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
Content
</div>
</div>
<!-- 13) Modal enter / exit (with framework) -->
<!-- React -->
<Transition
show={open}
enter="transition ease-out duration-200"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog />
</Transition>
<!-- 14) Animation utilities — predefined keyframes -->
<div class="animate-spin">…</div> <!-- rotate -->
<div class="animate-ping">…</div> <!-- pulse outward -->
<div class="animate-pulse">…</div> <!-- fade -->
<div class="animate-bounce">…</div> <!-- vertical bounce -->
<div class="animate-none">…</div>
<!-- 15) Custom animation in tailwind.config -->
/*
module.exports = {
theme: {
extend: {
keyframes: {
wiggle: {
'0%, 100%': { transform: 'rotate(-3deg)' },
'50%': { transform: 'rotate(3deg)' },
},
},
animation: {
wiggle: 'wiggle 1s ease-in-out infinite',
},
},
},
};
*/
<!-- Use: <div class="animate-wiggle">…</div> -->
<!-- 16) Performance tips -->
<!-- • Transition specific properties (transition-colors) instead of transition-all -->
<!-- • transform + opacity are GPU-accelerated — fast -->
<!-- • Avoid transitioning layout-affecting props (width, height, top, left) — reflow -->
<!-- • prefer translate over top/left, scale over width/height -->
<!-- • Use will-change sparingly — only for genuinely heavy animations -->
<!-- 17) Reduced motion — respect user preferences -->
<div class="transition-transform motion-reduce:transition-none">…</div>
<div class="animate-spin motion-reduce:animate-none">…</div>
<!-- Globally — index.html or main.css -->
<!--
@@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
-->
<!-- 18) Common patterns -->
<!-- Page enter -->
<div class="opacity-0 translate-y-2 [&.show]:opacity-100 [&.show]:translate-y-0 transition duration-500 ease-out">…</div>
<!-- Add 'show' class after mount -->
<!-- Skeleton loader -->
<div class="animate-pulse h-4 bg-slate-200 rounded w-full"></div>
<!-- Pulse around an alert -->
<button class="relative">
Notifications
<span class="absolute -top-1 -right-1 w-2 h-2 bg-rose-500 rounded-full animate-ping"></span>
</button>
<!-- 19) Common bugs -->
<!-- • transition without specifying properties → 'transition-all' is default in newer versions; transitions everything -->
<!-- • Animating width/height → janky on mobile; use scale + transform-origin -->
<!-- • Forgetting hover/focus → no transition trigger -->
<!-- • duration without transition utility → no effect -->
<!-- • motion-reduce not respected → accessibility issue -->
<!-- 20) When to use what -->
<!-- Tailwind transitions — simple hover/focus/state changes -->
<!-- Tailwind animations — looping decorative animations -->
<!-- Framer Motion / GSAP — complex page transitions, gestures, scroll-linked -->
<!-- View Transitions API — page transitions in modern browsers -->
Why it matters
Use specific transition props (transition-colors, transition-transform) over transition-all — cheaper and clearer. transform + opacity hit the GPU path; transitioning width/top forces reflow.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
<button class="transition-colors duration-200 hover:bg-emerald-600">…</button>Try it Yourself »
Discussion
Loading…