36 Tailwind CSS Button Hover Effects
29 / 36

All 36 in 36 Tailwind CSS Button Hover Effects

  1. 01Tailwind Magnetic Ripple Attraction Button Hover Effect
  2. 02Tailwind Cyberpunk Holographic Glitch Grid Button
  3. 03Tailwind Frosted Glassmorphism Shimmer Glow Button
  4. 04Tailwind Organic Blob Morph Button Hover Effect
  5. 05Tailwind Dual-Line Intersection Border Draw Button
  6. 06Tailwind Isometric Tactile 3D Depress Button
  7. 07Tailwind Infinite Sliding Kinetic Marquee Button
  8. 08Tailwind Chroma Conic Gradient Border Spin Button
  9. 09Tailwind Minimalist Border & Outline Drawing Hover Effects
  10. 10Tailwind Modern 3D Skeuomorphic Button Press Effects
  11. 11Tailwind Neo-Brutalist & Cyberpunk Button Glow Effects
  12. 12Tailwind Sliding Background Color Wipe Button Effects
  13. 13Tailwind Liquid Fill & Organic Morphing Button Effects
  14. 14Tailwind Kinetic Text Flip & Icon Reveal Button Effects
  15. 15Tailwind Liquid Wave Fill Button Hover Effect
  16. 16Tailwind Magnetic Border Drift Button
  17. 17Tailwind Glitch Slice Button Hover Effect
  18. 18Tailwind Neon Pulse Glow Button Hover Effect
  19. 19Tailwind Split Reveal Curtain Button Effect
  20. 20Tailwind Diagonal Shutter Sweep Button Effect
  21. 21Tailwind Elastic Lift Spring Button Hover Effect
  22. 22Tailwind Center Underline Draw Link Button Effects
  23. 23Tailwind 3D Flip Card Button Hover Effect
  24. 24Tailwind Particle Burst Confetti Button Effect
  25. 25Tailwind Slide Doors Closing Panel Button Effect
  26. 26Tailwind Typewriter Retype Terminal Button Effect
  27. 27Tailwind Hard Shadow Shift Flat Button Effect
  28. 28Tailwind Material Ripple Wave Button Effect
  29. 29Tailwind Rainbow Gradient Border Spin Button
  30. 30Tailwind Morph Shape Silhouette Button Effects
  31. 31Tailwind Icon Slide In Directional Button Effect
  32. 32Tailwind Cursor Spotlight Glow Button
  33. 33Tailwind Stagger Fill Equaliser Button Effect
  34. 34Tailwind Sunburst Expand Radiant Button Effect
  35. 35Tailwind 3D Press Plunger Key Button Effect
  36. 36Tailwind Add-to-Cart Liquid Glass Ripple Button
Pure TailwindMIT licensed

Tailwind Rainbow Gradient Border Spin Button

A vivid CTA framed by a rotating full-spectrum gradient border with a soft blurred glow bleeding behind it — the 'AI / Pro' badge look. Unlike entry 08 it rotates the LAYER rather than a registered angle, so it needs no @property and works further back.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<div class="tbh-29-group w-full min-h-svh flex flex-wrap">
<section class="tbh-29a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh29-sans bg-tbh29a-stage" aria-label="Rainbow border spin button">
  <div class="group/btn relative isolate overflow-hidden rounded-[22px] p-2">
    <span aria-hidden="true" class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[150%] aspect-square -z-10 blur-[18px] opacity-55 bg-[conic-gradient(var(--color-tbh29a-c1),var(--color-tbh29a-c2),var(--color-tbh29a-c3),var(--color-tbh29a-c4),var(--color-tbh29a-c5),var(--color-tbh29a-c6),var(--color-tbh29a-c1))] animate-tbh29a-spin transition-opacity duration-300 group-hover/btn:opacity-85 group-hover/btn:[animation-duration:1.4s] motion-reduce:animate-none"></span>
    <button type="button" class="relative isolate overflow-hidden cursor-pointer border-0 rounded-[14px] px-[38px] py-4 text-base font-extrabold text-white bg-tbh29a-card transition-[translate] duration-200 before:content-[''] before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-[150%] before:aspect-square before:z-0 before:bg-[conic-gradient(var(--color-tbh29a-c1),var(--color-tbh29a-c2),var(--color-tbh29a-c3),var(--color-tbh29a-c4),var(--color-tbh29a-c5),var(--color-tbh29a-c6),var(--color-tbh29a-c1))] before:animate-tbh29a-spin hover:-translate-y-0.5 hover:before:[animation-duration:1.4s] focus-visible:-translate-y-0.5 focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:before:animate-none motion-reduce:hover:translate-y-0">
      <span aria-hidden="true" class="absolute inset-0.5 z-[1] rounded-xl bg-tbh29a-card"></span>
      <span class="relative z-[2]">Upgrade to Pro</span>
    </button>
  </div>
</section>
<section class="tbh-29b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh29-sans bg-tbh29b-stage" aria-label="Duotone border spin button">
  <button type="button" class="relative isolate overflow-hidden cursor-pointer border-0 rounded-full px-10 py-4 text-base font-extrabold text-white bg-tbh29b-card transition-[translate] duration-200 before:content-[''] before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-[160%] before:aspect-square before:z-0 before:bg-[conic-gradient(from_0deg,var(--color-tbh29b-c1),var(--color-tbh29b-c2),var(--color-tbh29b-c1))] before:animate-tbh29b-spin hover:-translate-y-0.5 hover:before:[animation-duration:1.2s] focus-visible:-translate-y-0.5 focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:before:animate-none motion-reduce:hover:translate-y-0">
    <span aria-hidden="true" class="absolute inset-0.5 z-[1] rounded-full bg-tbh29b-card"></span>
    <span class="relative z-[2]">Go premium</span>
  </button>
</section>
</div>
@import "tailwindcss";

@theme {
  --color-tbh29a-card: #12121a;
  --color-tbh29a-card: oklch(0.18 0.015 285);
  --color-tbh29a-stage: #07070d;
  --color-tbh29a-stage: oklch(0.11 0.01 285);
  --color-tbh29a-c1: #ff3d81;
  --color-tbh29a-c1: oklch(0.68 0.24 0);
  --color-tbh29a-c2: #ffb03d;
  --color-tbh29a-c2: oklch(0.82 0.17 70);
  --color-tbh29a-c3: #f5f13d;
  --color-tbh29a-c3: oklch(0.93 0.19 105);
  --color-tbh29a-c4: #3dff8b;
  --color-tbh29a-c4: oklch(0.89 0.22 150);
  --color-tbh29a-c5: #3dc9ff;
  --color-tbh29a-c5: oklch(0.8 0.15 225);
  --color-tbh29a-c6: #8b3dff;
  --color-tbh29a-c6: oklch(0.55 0.28 295);
  --color-tbh29b-card: #0e1220;
  --color-tbh29b-card: oklch(0.17 0.025 265);
  --color-tbh29b-stage: #060810;
  --color-tbh29b-stage: oklch(0.1 0.015 265);
  --color-tbh29b-c1: #3d7bff;
  --color-tbh29b-c1: oklch(0.6 0.22 265);
  --color-tbh29b-c2: #b03dff;
  --color-tbh29b-c2: oklch(0.58 0.27 305);
  --font-tbh29-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh29a-spin: tbh29a-spin 4s linear infinite;
  --animate-tbh29b-spin: tbh29b-spin 3s linear infinite;
}
/* Stays CSS: the spin keyframes — and note what they no longer carry. The layers are centred
   with -translate-x-1/2 / -translate-y-1/2 on the discrete translate property, so rotation
   is all the keyframe owns. In the CSS original every stop restated translate(-50%,-50%). */

@keyframes tbh29a-spin {
  to {
    rotate: 360deg;
  }
}

@keyframes tbh29b-spin {
  to {
    rotate: 360deg;
  }
}

.tbh-29-group {
  width: 100%;
  min-height: 100svh;
}

.tbh-29a,
.tbh-29b {
  min-height: 100svh;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tbh29a-card: #12121a;
  --color-tbh29a-card: oklch(0.18 0.015 285);
  --color-tbh29a-stage: #07070d;
  --color-tbh29a-stage: oklch(0.11 0.01 285);
  --color-tbh29a-c1: #ff3d81;
  --color-tbh29a-c1: oklch(0.68 0.24 0);
  --color-tbh29a-c2: #ffb03d;
  --color-tbh29a-c2: oklch(0.82 0.17 70);
  --color-tbh29a-c3: #f5f13d;
  --color-tbh29a-c3: oklch(0.93 0.19 105);
  --color-tbh29a-c4: #3dff8b;
  --color-tbh29a-c4: oklch(0.89 0.22 150);
  --color-tbh29a-c5: #3dc9ff;
  --color-tbh29a-c5: oklch(0.8 0.15 225);
  --color-tbh29a-c6: #8b3dff;
  --color-tbh29a-c6: oklch(0.55 0.28 295);
  --color-tbh29b-card: #0e1220;
  --color-tbh29b-card: oklch(0.17 0.025 265);
  --color-tbh29b-stage: #060810;
  --color-tbh29b-stage: oklch(0.1 0.015 265);
  --color-tbh29b-c1: #3d7bff;
  --color-tbh29b-c1: oklch(0.6 0.22 265);
  --color-tbh29b-c2: #b03dff;
  --color-tbh29b-c2: oklch(0.58 0.27 305);
  --font-tbh29-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh29a-spin: tbh29a-spin 4s linear infinite;
  --animate-tbh29b-spin: tbh29b-spin 3s linear infinite;
}
/* Stays CSS: the spin keyframes — and note what they no longer carry. The layers are centred
   with -translate-x-1/2 / -translate-y-1/2 on the discrete translate property, so rotation
   is all the keyframe owns. In the CSS original every stop restated translate(-50%,-50%). */

@keyframes tbh29a-spin {
  to {
    rotate: 360deg;
  }
}

@keyframes tbh29b-spin {
  to {
    rotate: 360deg;
  }
}

.tbh-29-group {
  width: 100%;
  min-height: 100svh;
}

.tbh-29a,
.tbh-29b {
  min-height: 100svh;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • The keyframes shrank to to { rotate: 360deg }. The CSS original had to write transform: translate(-50%,-50%) rotate(360deg) because one property held both the centring and the spin; v4's discrete properties mean the keyframe describes only the motion.
  • Six gradient stops became six @theme colours, which is more verbose in the stylesheet and much better in practice: the glow layer reuses the identical gradient by reference, so the rim and its blurred copy can never drift apart.
  • UI change from the CSS original: the hover lift fires on focus-visible: too, and design A's glow opacity now rises on hover (0.55 → 0.85) in step with the speed-up rather than staying fixed.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Rainbow Gradient Border Spin Button
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-rainbow-gradient-border-spin-button/

A vivid CTA framed by a rotating full-spectrum gradient border with a soft blurred glow bleeding behind it &mdash; the 'AI / Pro' badge look. Unlike entry 08 it rotates the LAYER rather than a registered angle, so it needs no @property and works further back.
## HTML
```html
<div class="tbh-29-group w-full min-h-svh flex flex-wrap">
<section class="tbh-29a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh29-sans bg-tbh29a-stage" aria-label="Rainbow border spin button">
  <div class="group/btn relative isolate overflow-hidden rounded-[22px] p-2">
    <span aria-hidden="true" class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[150%] aspect-square -z-10 blur-[18px] opacity-55 bg-[conic-gradient(var(--color-tbh29a-c1),var(--color-tbh29a-c2),var(--color-tbh29a-c3),var(--color-tbh29a-c4),var(--color-tbh29a-c5),var(--color-tbh29a-c6),var(--color-tbh29a-c1))] animate-tbh29a-spin transition-opacity duration-300 group-hover/btn:opacity-85 group-hover/btn:[animation-duration:1.4s] motion-reduce:animate-none"></span>
    <button type="button" class="relative isolate overflow-hidden cursor-pointer border-0 rounded-[14px] px-[38px] py-4 text-base font-extrabold text-white bg-tbh29a-card transition-[translate] duration-200 before:content-[''] before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-[150%] before:aspect-square before:z-0 before:bg-[conic-gradient(var(--color-tbh29a-c1),var(--color-tbh29a-c2),var(--color-tbh29a-c3),var(--color-tbh29a-c4),var(--color-tbh29a-c5),var(--color-tbh29a-c6),var(--color-tbh29a-c1))] before:animate-tbh29a-spin hover:-translate-y-0.5 hover:before:[animation-duration:1.4s] focus-visible:-translate-y-0.5 focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:before:animate-none motion-reduce:hover:translate-y-0">
      <span aria-hidden="true" class="absolute inset-0.5 z-[1] rounded-xl bg-tbh29a-card"></span>
      <span class="relative z-[2]">Upgrade to Pro</span>
    </button>
  </div>
</section>
<section class="tbh-29b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh29-sans bg-tbh29b-stage" aria-label="Duotone border spin button">
  <button type="button" class="relative isolate overflow-hidden cursor-pointer border-0 rounded-full px-10 py-4 text-base font-extrabold text-white bg-tbh29b-card transition-[translate] duration-200 before:content-[''] before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-[160%] before:aspect-square before:z-0 before:bg-[conic-gradient(from_0deg,var(--color-tbh29b-c1),var(--color-tbh29b-c2),var(--color-tbh29b-c1))] before:animate-tbh29b-spin hover:-translate-y-0.5 hover:before:[animation-duration:1.2s] focus-visible:-translate-y-0.5 focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:before:animate-none motion-reduce:hover:translate-y-0">
    <span aria-hidden="true" class="absolute inset-0.5 z-[1] rounded-full bg-tbh29b-card"></span>
    <span class="relative z-[2]">Go premium</span>
  </button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tbh29a-card: #12121a;
  --color-tbh29a-card: oklch(0.18 0.015 285);
  --color-tbh29a-stage: #07070d;
  --color-tbh29a-stage: oklch(0.11 0.01 285);
  --color-tbh29a-c1: #ff3d81;
  --color-tbh29a-c1: oklch(0.68 0.24 0);
  --color-tbh29a-c2: #ffb03d;
  --color-tbh29a-c2: oklch(0.82 0.17 70);
  --color-tbh29a-c3: #f5f13d;
  --color-tbh29a-c3: oklch(0.93 0.19 105);
  --color-tbh29a-c4: #3dff8b;
  --color-tbh29a-c4: oklch(0.89 0.22 150);
  --color-tbh29a-c5: #3dc9ff;
  --color-tbh29a-c5: oklch(0.8 0.15 225);
  --color-tbh29a-c6: #8b3dff;
  --color-tbh29a-c6: oklch(0.55 0.28 295);
  --color-tbh29b-card: #0e1220;
  --color-tbh29b-card: oklch(0.17 0.025 265);
  --color-tbh29b-stage: #060810;
  --color-tbh29b-stage: oklch(0.1 0.015 265);
  --color-tbh29b-c1: #3d7bff;
  --color-tbh29b-c1: oklch(0.6 0.22 265);
  --color-tbh29b-c2: #b03dff;
  --color-tbh29b-c2: oklch(0.58 0.27 305);
  --font-tbh29-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh29a-spin: tbh29a-spin 4s linear infinite;
  --animate-tbh29b-spin: tbh29b-spin 3s linear infinite;
}
/* Stays CSS: the spin keyframes — and note what they no longer carry. The layers are centred
   with -translate-x-1/2 / -translate-y-1/2 on the discrete translate property, so rotation
   is all the keyframe owns. In the CSS original every stop restated translate(-50%,-50%). */

@keyframes tbh29a-spin {
  to {
    rotate: 360deg;
  }
}

@keyframes tbh29b-spin {
  to {
    rotate: 360deg;
  }
}

.tbh-29-group {
  width: 100%;
  min-height: 100svh;
}

.tbh-29a,
.tbh-29b {
  min-height: 100svh;
}
```

How this works

Rotate the paint, not the angle. Entry 08 animates a registered <angle> inside the gradient; this one rotates an oversized layer that happens to be painted with a gradient. The result looks nearly identical, needs no @property, and is the technique to reach for when support floor matters — the trade is that the layer must be large enough that its corners never enter the button.

The glow is a copy. after: duplicates the layer, blurs it, drops it behind with a negative z-index and lowers its opacity. One extra element would do the same, but a pseudo-element keeps the DOM at one node and the two layers provably in sync (same keyframe, same duration).

The cover is a real span. Both pseudo slots are used, so the inner mask has to be an element — absolute inset-0.5 in the card colour, which is what turns a full gradient into a 2px rim.

Make it yours

  • Palette: the conic stops — design A is a six-stop spectrum, B a two-colour duotone that reads far more corporate.
  • Speed: --animate-tbh29a-spin (4s) and the hover override (1.4s).
  • Rim thickness: the cover's inset-0.5; inset-px for a hairline.
  • Glow strength: after:blur-[18px] after:opacity-55, rising to hover:after:opacity-85.

Gotchas — read before shipping

  • Oversize the rotating layer (150–160%) or its square corners sweep into view as it turns — the classic failure of this technique.
  • The cover span must be fully opaque and exactly the card colour, or the gradient shows through as a wash.
  • Pick this OR entry 08 on a given page, not both: two different spinning-border implementations side by side is an inconsistency a reader will notice before a designer does.
  • The blurred after: layer sits at -z-10, which only works because the button carries isolate — otherwise it paints behind the page background.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Rotating a gradient-painted layer works wherever transforms do; this is the wider-support alternative to entry 08's @property approach.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Plain CSSno Tailwind surface

Search CodeFronts

Loading…