Built-Ins Plus Your Own @keyframes
Animations & Keyframes
Use the built-in animation utilities for common effects and define custom keyframe animations directly in CSS via @theme.
What you'll learn
- Use animate-spin, ping, pulse, and bounce
- Define a custom animation token in @theme
- Pause animations and respect reduced motion
Transitions interpolate between two states; animations run a keyframe sequence on a loop. Tailwind ships four ready-made ones and lets you author your own in CSS.
Built-In Animations
These cover the bulk of UI motion needs:
<svg class="animate-spin h-5 w-5">...</svg>
<span class="relative flex h-3 w-3">
<span class="animate-ping absolute h-full w-full rounded-full
bg-blue-400 opacity-75"></span>
<span class="relative h-3 w-3 rounded-full bg-blue-500"></span>
</span>
<div class="animate-pulse h-4 w-48 rounded bg-gray-200"></div> animate-spin drives loading spinners, animate-ping makes notification dots radiate, animate-pulse builds skeleton loaders, and animate-bounce nudges scroll hints.
Custom Animations in @theme
Define a new animation as a theme token and its @keyframes alongside it. Tailwind generates the matching animate-* utility:
@import "tailwindcss";
@theme {
--animate-wiggle: wiggle 1s ease-in-out infinite;
}
@keyframes wiggle {
0%, 100% { transform: rotate(-3deg); }
50% { transform: rotate(3deg); }
} The --animate-wiggle token produces an animate-wiggle class you can apply and combine with variants like hover:animate-wiggle.
Pausing and Reduced Motion
You can pause an animation on demand and must offer an escape from continuous motion:
<div class="animate-spin hover:[animation-play-state:paused]
motion-reduce:animate-none">
Pauses on hover, stops entirely for reduced-motion users
</div> motion-reduce:animate-none is essential for looping animations — perpetual movement can cause discomfort, so always provide it.