Animations & Keyframes

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.

4 min read Level 3/5 #tailwind#animations#keyframes
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.

Transforms →