FrontendJuly 25, 20256 min read

Mastering Tailwind CSS Animations

Tailwind gives you the primitives. Here's how to combine them into animations that feel intentional, smooth, and nothing like every other dev portfolio.

Mastering Tailwind CSS Animations

Most Tailwind animations on the internet look the same: a `hover:scale-105` here, a `transition-all` there, maybe a `hover:shadow-purple-500` if someone's feeling adventurous. They work, but they don't feel crafted. Good animations have purpose - they communicate state changes, guide attention, and reward interaction. Here's how to do that with Tailwind.

# The Foundation: transition, duration, ease

Every animated element needs three things: what to animate, how long, and what easing curve. Tailwind's defaults are reasonable but generic. Be intentional:

html
<!-- Generic and forgettable -->
<button class="hover:bg-blue-600 transition-all duration-300">Click me</button>

<!-- Intentional - only animates background and shadow, custom easing -->
<button class="
  bg-teal-600
  hover:bg-teal-500
  hover:shadow-[0_0_20px_rgba(13,148,136,0.4)]
  transition-[background-color,box-shadow]
  duration-200
  ease-out
">
  Click me
</button>

`transition-all` animates every property including layout ones like `width` and `height` - this forces the browser to do expensive layout recalculations. Only animate `transform`, `opacity`, `background-color`, and `box-shadow` for 60fps smoothness.

# Card Hover Effects That Actually Look Good

html
<!-- Lift + glow - elegant for dark UIs -->
<div class="
  group
  rounded-xl
  border border-white/5
  bg-white/3
  p-6
  transition-all duration-300
  hover:-translate-y-1.5
  hover:border-teal-500/40
  hover:shadow-[0_8px_30px_rgba(13,148,136,0.15)]
  cursor-pointer
">
  <!-- Arrow icon that moves on hover -->
  <span class="
    inline-block
    transition-transform duration-200
    group-hover:translate-x-1
    group-hover:-translate-y-1
  ">
    ↗
  </span>
</div>

# Custom Keyframe Animations in Tailwind

Tailwind's built-in animations are limited to `spin`, `ping`, `pulse`, and `bounce`. For anything custom, extend your config:

javascript
// tailwind.config.ts
export default {
  theme: {
    extend: {
      keyframes: {
        "fade-up": {
          "0%":   { opacity: "0", transform: "translateY(16px)" },
          "100%": { opacity: "1", transform: "translateY(0)" },
        },
        "shimmer": {
          "0%":   { backgroundPosition: "-200% 0" },
          "100%": { backgroundPosition: "200% 0" },
        },
        "blink": {
          "0%, 100%": { opacity: "1" },
          "50%":      { opacity: "0" },
        },
      },
      animation: {
        "fade-up":  "fade-up 0.5s ease-out forwards",
        "shimmer":  "shimmer 2s linear infinite",
        "blink":    "blink 1s step-end infinite",
      },
    },
  },
};
html
<!-- Skeleton loading shimmer effect -->
<div class="
  h-4 w-48 rounded
  bg-gradient-to-r from-white/5 via-white/10 to-white/5
  bg-[length:200%_100%]
  animate-shimmer
" />

<!-- Staggered fade-up for lists -->
<ul>
  <li class="animate-fade-up [animation-delay:0ms]">Item 1</li>
  <li class="animate-fade-up [animation-delay:100ms]">Item 2</li>
  <li class="animate-fade-up [animation-delay:200ms]">Item 3</li>
</ul>

# The Typewriter Cursor (No Library Needed)

html
<!-- Blinking cursor using the custom blink animation -->
<p class="font-mono text-lg">
  Full-Stack Developer
  <span class="
    inline-block w-0.5 h-5 ml-0.5
    bg-teal-400
    align-middle
    animate-blink
  " />
</p>

# Rules for Animations That Don't Annoy People

  • Duration under 300ms for micro-interactions (hover, click). Longer feels laggy.
  • Duration 400-700ms for page transitions and entrance animations. Longer feels cinematic (in a bad way).
  • Use `ease-out` for things appearing - they start fast and settle. Use `ease-in` for things disappearing.
  • Respect `prefers-reduced-motion` - wrap animations with `motion-safe:` prefix in Tailwind.
  • Animate one thing at a time per element. Multiple simultaneous animations fight for attention.
html
<!-- Respects user's OS motion preference -->
<div class="motion-safe:animate-fade-up motion-reduce:opacity-100">
  Accessible animation
</div>

Written by

Muhiu Din

Full-Stack Engineer

More Articles