Tailwind Transitions and Animations
A transition is a smooth change from one style to another. An animation plays a sequence of style changes automatically. Tailwind provides utility classes for both — so you get smooth, polished motion without writing custom CSS keyframes.
What Is a CSS Transition?
Without a transition, style changes happen instantly — like flipping a light switch. With a transition, the change slides smoothly from the start value to the end value — like a dimmer switch.
Without transition:
Button → [BLUE] ... cursor moves over ... [DARK BLUE instantly]
With transition:
Button → [BLUE] ... cursor moves over ... [blue fades to DARK BLUE]The transition Class
Adding transition to an element enables smooth changes for common properties: color, background, border, opacity, shadow, and transform.
<!-- No transition (instant change) -->
<button class="bg-blue-500 hover:bg-blue-700 text-white px-4 py-2 rounded">
Instant
</button>
<!-- With transition (smooth change) -->
<button class="bg-blue-500 hover:bg-blue-700 text-white px-4 py-2 rounded transition">
Smooth
</button>Transition Scope Classes
Use these to limit which properties transition.
transition → colors, background, border, box-shadow, opacity, transform
transition-colors → only color-related properties
transition-opacity → only opacity
transition-shadow → only box-shadow
transition-transform → only transform (scale, rotate, translate)
transition-all → every CSS property
transition-none → no transitions at allWhy Limit Transitions?
transition-all → every property changes smoothly
(can cause unexpected lag in complex layouts)
transition-colors → only text/bg color changes smoothly
(faster, more predictable)Transition Duration
Duration controls how long the transition takes. Like pouring water — a short duration pours fast, a long one pours slowly.
duration-0 → 0ms (instant)
duration-75 → 75ms (very fast)
duration-100 → 100ms (fast)
duration-150 → 150ms (snappy — good for buttons)
duration-200 → 200ms (comfortable)
duration-300 → 300ms (smooth — good for cards)
duration-500 → 500ms (slow)
duration-700 → 700ms (very slow)
duration-1000 → 1000ms (one full second)<button class="bg-blue-500 hover:bg-blue-700 transition-colors duration-200 text-white px-4 py-2 rounded">
200ms transition
</button>Transition Timing Function (Easing)
Easing controls the speed curve of a transition. Does it start fast and slow down? Or start slow and speed up?
ease-linear → constant speed throughout
ease-in → starts slow, ends fast (like a car accelerating)
ease-out → starts fast, ends slow (like a car braking)
ease-in-out → slow start, fast middle, slow end (most natural)<div class="hover:translate-x-4 transition-transform duration-300 ease-in-out">
Slides naturally
</div>Easing Speed Curve Diagram
ease-linear: ────────────── (steady)
ease-in: ─────╱╱╱╱╱╱ (slow then fast)
ease-out: ╱╱╱╱╱╱───── (fast then slow)
ease-in-out: ──╱╱╱╱╱╱── (slow, fast, slow)Transition Delay
Delay waits before starting the transition. Useful for staggered effects where items appear one after another.
delay-0 → starts immediately
delay-75 → waits 75ms
delay-100 → waits 100ms
delay-150 → waits 150ms
delay-300 → waits 300ms
delay-500 → waits 500ms
delay-700 → waits 700ms
delay-1000 → waits 1 second<div class="hover:opacity-100 opacity-0 transition-opacity duration-300 delay-150">
Fades in after 150ms delay
</div>Transform Utilities
Transforms move, resize, and rotate elements. Pair them with transition for smooth motion.
Translate (Move)
<div class="hover:translate-x-2">Moves 8px right on hover</div>
<div class="hover:-translate-x-2">Moves 8px left on hover</div>
<div class="hover:translate-y-2">Moves 8px down on hover</div>
<div class="hover:-translate-y-2">Moves 8px up on hover</div>Translate Directions
-translate-y-2 (up)
↑
-translate-x-2 ← [element] → translate-x-2
↓
translate-y-2 (down)Scale (Resize)
<div class="hover:scale-105">Grows 5% on hover</div>
<div class="hover:scale-110">Grows 10% on hover</div>
<div class="hover:scale-95">Shrinks 5% on hover (press effect)</div>
<div class="hover:scale-150">Grows 50%</div>Scale Diagram
scale-90 → [ small ]
scale-100 → [ normal ] (default)
scale-105 → [ slightly bigger ]
scale-110 → [ bigger ]
scale-125 → [ big ]Rotate
<div class="hover:rotate-6">Tilts 6 degrees clockwise</div>
<div class="hover:-rotate-6">Tilts 6 degrees counter-clockwise</div>
<div class="hover:rotate-45">Rotates 45 degrees</div>
<div class="hover:rotate-180">Flips upside down</div>Skew
<div class="skew-x-3">Skewed horizontally</div>
<div class="skew-y-3">Skewed vertically</div>Full Transition Button Example
<button class="
bg-blue-500 text-white px-6 py-3 rounded-lg
hover:bg-blue-700
hover:scale-105
hover:shadow-lg
active:scale-95
transition-all duration-200 ease-in-out
">
Interactive Button
</button>Interaction Timeline
Idle: [bg-blue-500, scale-100, shadow-none]
Hover: [bg-blue-700, scale-105, shadow-lg] ← all change smoothly in 200ms
Press: [bg-blue-700, scale-95, shadow-lg] ← scales down instantlyTailwind Animations
Tailwind includes four built-in CSS animations you can apply with a single class. No keyframe code needed.
animate-spin
Continuously rotates an element. Use this for loading spinners.
<svg class="animate-spin h-6 w-6 text-blue-500" viewBox="0 0 24 24">
...
</svg>
<!-- Or any element -->
<div class="animate-spin w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full"></div>Spinner Pattern Explained
border-4 → thick border on all sides
border-blue-500 → blue color
border-t-transparent → top side is invisible
rounded-full → makes it a circle
animate-spin → rotates forever
Result: a circle with a gap at the top that spins = loading indicatoranimate-ping
Expands and fades out — like a radar ping or a notification badge pulse.
<span class="relative flex h-3 w-3">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-blue-500"></span>
</span>Ping Animation Diagram
Frame 1: [●] ← small dot
Frame 2: [●]◌ ← ring expands
Frame 3: [●] ◌ ← ring fades out further
Frame 4: [●] ← resets and repeatsanimate-bounce
Moves an element up and down repeatedly. Use for scroll indicators or attention-grabbing arrows.
<span class="animate-bounce text-2xl">↓</span>
<!-- Bouncing "scroll down" indicator -->
<div class="flex justify-center mt-8">
<svg class="animate-bounce w-6 h-6 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>animate-pulse
Fades between full opacity and 50% opacity. Use for skeleton loading screens — placeholders shown while content loads.
<!-- Skeleton card loading placeholder -->
<div class="border rounded-lg p-4 space-y-3">
<div class="animate-pulse bg-gray-200 h-4 rounded w-3/4"></div>
<div class="animate-pulse bg-gray-200 h-4 rounded w-full"></div>
<div class="animate-pulse bg-gray-200 h-4 rounded w-5/6"></div>
</div>Pulse Skeleton Diagram
┌──────────────────────────────────┐
│ ████████████████████░░░ │ ← animate-pulse (fading gray bar)
│ █████████████████████████░ │
│ ████████████████████████ │
└──────────────────────────────────┘
Content appears → skeleton disappearsControlling Animation Behavior
animate-none
Removes any animation from an element. Useful for stopping inherited animations.
<div class="animate-spin md:animate-none">
Spins on mobile, static on desktop
</div>Respecting Reduced Motion
Some users have motion sensitivity and enable "Reduce Motion" in their OS settings. Always provide a no-animation fallback.
<div class="animate-spin motion-reduce:animate-none">
Spins normally, pauses for users who prefer less motion
</div>
<div class="transition-all duration-500 motion-reduce:transition-none hover:translate-y-2">
Moves on hover, no movement for sensitive users
</div>Combining Transitions and Animations: Practical Patterns
Fade-In on Load
<div class="opacity-0 animate-[fadeIn_0.5s_ease-in_forwards]">
Content fades in
</div>Card Lift on Hover
<div class="bg-white rounded-xl shadow-md hover:shadow-xl hover:-translate-y-1 transition-all duration-300 p-6">
<h3>Product Title</h3>
<p>Description text here.</p>
</div>Sliding Side Menu
<!-- Menu starts off-screen, slides in on open -->
<div class="-translate-x-full open:translate-x-0 transition-transform duration-300 ease-out fixed left-0 top-0 h-full w-64 bg-white shadow-xl">
Menu Content
</div>Quick Reference Table
PURPOSE CLASS(ES)
──────────────────────────────────────────────────
Enable transitions transition
Specific property only transition-colors / transition-transform
Control speed duration-150 to duration-1000
Choose easing ease-in-out
Add delay delay-300
Move on hover hover:translate-x-2
Grow on hover hover:scale-105
Shrink on press active:scale-95
Rotate on hover hover:rotate-6
Spinning loader animate-spin
Notification pulse animate-ping
Scroll arrow bounce animate-bounce
Loading skeleton animate-pulse
Disable for motion users motion-reduce:animate-none