36 Tailwind CSS Button Hover Effects
30 / 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 Morph Shape Silhouette Button Effects

Three silhouette morphs: sharp corners rounding into a pill, a pill snapping to an asymmetric notch, and a circular icon button expanding into a labelled bar. The third is the one worth copying — a floating action button that earns its label on hover.

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-30-group w-full min-h-svh flex flex-wrap">
<section class="tbh-30a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh30-sans bg-tbh30a-stage" aria-label="Morph shape button">
  <button type="button" class="cursor-pointer border-0 rounded px-[38px] py-4 text-base font-extrabold text-white bg-tbh30a-acc shadow-[0_10px_22px_-12px_color-mix(in_oklab,var(--color-tbh30a-acc)_70%,transparent)] transition-[border-radius,translate,scale,background-color] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:rounded-[30px] hover:-translate-y-0.5 hover:bg-[color-mix(in_oklab,var(--color-tbh30a-acc)_88%,black)] focus-visible:rounded-[30px] focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-tbh30a-acc focus-visible:outline-offset-4 motion-reduce:transition-[border-radius,background-color] motion-reduce:duration-[250ms] motion-reduce:hover:translate-y-0">
    Send message
  </button>
</section>
<section class="tbh-30b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh30-sans bg-tbh30b-stage" aria-label="Pill to notched button">
  <button type="button" class="cursor-pointer border-0 rounded-[30px] px-10 py-4 text-base font-extrabold text-white bg-tbh30b-acc shadow-[0_12px_24px_-12px_var(--color-tbh30b-acc)] transition-[border-radius,translate,scale] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:[border-radius:16px_4px_16px_4px] hover:-translate-y-0.5 focus-visible:[border-radius:16px_4px_16px_4px] focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:transition-[border-radius] motion-reduce:duration-[250ms] motion-reduce:hover:translate-y-0">
    Reserve seat
  </button>
</section>
<section class="tbh-30c flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh30-sans bg-tbh30c-stage" aria-label="Circle to bar button">
  <button type="button" class="group/btn relative grid place-items-center overflow-hidden h-14 w-14 cursor-pointer border-0 rounded-[28px] text-base font-extrabold text-white bg-tbh30c-acc shadow-[0_12px_24px_-12px_var(--color-tbh30c-acc)] transition-[width,border-radius] duration-[450ms] ease-[cubic-bezier(.4,0,.2,1)] hover:w-[170px] hover:rounded-[14px] focus-visible:w-[170px] focus-visible:rounded-[14px] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:transition-none">
    <span aria-hidden="true" class="text-2xl leading-none transition-opacity duration-200 group-hover/btn:opacity-0 group-hover/btn:duration-150 group-focus-visible/btn:opacity-0">&#65291;</span>
    <span class="absolute whitespace-nowrap opacity-0 transition-opacity duration-200 group-hover/btn:opacity-100 group-hover/btn:delay-[250ms] group-focus-visible/btn:opacity-100 group-focus-visible/btn:delay-[250ms]">Add item</span>
  </button>
</section>
</div>
@import "tailwindcss";

@theme {
  --color-tbh30a-acc: #3d8fb8;
  --color-tbh30a-acc: oklch(0.58 0.17 210);
  --color-tbh30a-stage: #f4f6f8;
  --color-tbh30a-stage: oklch(0.97 0.005 220);
  --color-tbh30b-acc: #d4664a;
  --color-tbh30b-acc: oklch(0.6 0.16 25);
  --color-tbh30b-stage: #1a1010;
  --color-tbh30b-stage: oklch(0.18 0.02 25);
  --color-tbh30c-acc: #4aab72;
  --color-tbh30c-acc: oklch(0.62 0.16 150);
  --color-tbh30c-stage: #0c160f;
  --color-tbh30c-stage: oklch(0.15 0.02 150);
  --font-tbh30-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: three radius targets and one width expansion. */

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

.tbh-30a,
.tbh-30b,
.tbh-30c {
  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-tbh30a-acc: #3d8fb8;
  --color-tbh30a-acc: oklch(0.58 0.17 210);
  --color-tbh30a-stage: #f4f6f8;
  --color-tbh30a-stage: oklch(0.97 0.005 220);
  --color-tbh30b-acc: #d4664a;
  --color-tbh30b-acc: oklch(0.6 0.16 25);
  --color-tbh30b-stage: #1a1010;
  --color-tbh30b-stage: oklch(0.18 0.02 25);
  --color-tbh30c-acc: #4aab72;
  --color-tbh30c-acc: oklch(0.62 0.16 150);
  --color-tbh30c-stage: #0c160f;
  --color-tbh30c-stage: oklch(0.15 0.02 150);
  --font-tbh30-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: three radius targets and one width expansion. */

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

.tbh-30a,
.tbh-30b,
.tbh-30c {
  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.

  • Design C is the port's best showing in this entry: the label sequencing (group-hover/btn:duration-150 out, group-hover/btn:delay-[250ms] in) is stated on the two labels themselves, where in CSS it was two transition-duration/transition-delay overrides in separate hover rules and very easy to desynchronise.
  • Design B's asymmetric target has to be an arbitrary [border-radius:16px_4px_16px_4px] — Tailwind's per-corner utilities could express it in four classes, but the single value keeps the shape readable as one decision.
  • UI change from the CSS original: all three morphs fire on focus-visible:, and designs A and B gained active: states that compose a scale with the lift rather than replacing the transform.
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 Morph Shape Silhouette Button Effects
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-morph-shape-silhouette-button-effects/

Three silhouette morphs: sharp corners rounding into a pill, a pill snapping to an asymmetric notch, and a circular icon button expanding into a labelled bar. The third is the one worth copying &mdash; a floating action button that earns its label on hover.
## HTML
```html
<div class="tbh-30-group w-full min-h-svh flex flex-wrap">
<section class="tbh-30a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh30-sans bg-tbh30a-stage" aria-label="Morph shape button">
  <button type="button" class="cursor-pointer border-0 rounded px-[38px] py-4 text-base font-extrabold text-white bg-tbh30a-acc shadow-[0_10px_22px_-12px_color-mix(in_oklab,var(--color-tbh30a-acc)_70%,transparent)] transition-[border-radius,translate,scale,background-color] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:rounded-[30px] hover:-translate-y-0.5 hover:bg-[color-mix(in_oklab,var(--color-tbh30a-acc)_88%,black)] focus-visible:rounded-[30px] focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-tbh30a-acc focus-visible:outline-offset-4 motion-reduce:transition-[border-radius,background-color] motion-reduce:duration-[250ms] motion-reduce:hover:translate-y-0">
    Send message
  </button>
</section>
<section class="tbh-30b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh30-sans bg-tbh30b-stage" aria-label="Pill to notched button">
  <button type="button" class="cursor-pointer border-0 rounded-[30px] px-10 py-4 text-base font-extrabold text-white bg-tbh30b-acc shadow-[0_12px_24px_-12px_var(--color-tbh30b-acc)] transition-[border-radius,translate,scale] duration-500 ease-[cubic-bezier(.4,0,.2,1)] hover:[border-radius:16px_4px_16px_4px] hover:-translate-y-0.5 focus-visible:[border-radius:16px_4px_16px_4px] focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:transition-[border-radius] motion-reduce:duration-[250ms] motion-reduce:hover:translate-y-0">
    Reserve seat
  </button>
</section>
<section class="tbh-30c flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh30-sans bg-tbh30c-stage" aria-label="Circle to bar button">
  <button type="button" class="group/btn relative grid place-items-center overflow-hidden h-14 w-14 cursor-pointer border-0 rounded-[28px] text-base font-extrabold text-white bg-tbh30c-acc shadow-[0_12px_24px_-12px_var(--color-tbh30c-acc)] transition-[width,border-radius] duration-[450ms] ease-[cubic-bezier(.4,0,.2,1)] hover:w-[170px] hover:rounded-[14px] focus-visible:w-[170px] focus-visible:rounded-[14px] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4 motion-reduce:transition-none">
    <span aria-hidden="true" class="text-2xl leading-none transition-opacity duration-200 group-hover/btn:opacity-0 group-hover/btn:duration-150 group-focus-visible/btn:opacity-0">&#65291;</span>
    <span class="absolute whitespace-nowrap opacity-0 transition-opacity duration-200 group-hover/btn:opacity-100 group-hover/btn:delay-[250ms] group-focus-visible/btn:opacity-100 group-focus-visible/btn:delay-[250ms]">Add item</span>
  </button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tbh30a-acc: #3d8fb8;
  --color-tbh30a-acc: oklch(0.58 0.17 210);
  --color-tbh30a-stage: #f4f6f8;
  --color-tbh30a-stage: oklch(0.97 0.005 220);
  --color-tbh30b-acc: #d4664a;
  --color-tbh30b-acc: oklch(0.6 0.16 25);
  --color-tbh30b-stage: #1a1010;
  --color-tbh30b-stage: oklch(0.18 0.02 25);
  --color-tbh30c-acc: #4aab72;
  --color-tbh30c-acc: oklch(0.62 0.16 150);
  --color-tbh30c-stage: #0c160f;
  --color-tbh30c-stage: oklch(0.15 0.02 150);
  --font-tbh30-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: three radius targets and one width expansion. */

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

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

How this works

Radius is the cheapest morph there is. Transitioning border-radius changes the silhouette without touching layout, so a square-to-pill morph costs nothing and never nudges a neighbour. Designs A and B are one utility each; the only real decision is what the target shape says.

Design C does animate width, on purpose. A 56px circle growing to 170px is a layout change, and that is acceptable here because the button is a floating action control with nothing beside it. The label timing is what makes it work: the glyph fades out fast (150ms) and the text arrives after a delay-[250ms], so the two never overlap mid-expansion.

Both endpoints must be intentional. A morph is a statement about two shapes. rounded (4px) to rounded-[30px] reads as 'formal becomes friendly'; the reverse reads as 'settle down'. Either is fine — drifting between two arbitrary radii is not.

Make it yours

  • Direction: swap the resting and hover radii to morph pill → square.
  • Partial morph: hover:rounded-tl-[30px] hover:rounded-br-[30px] for a two-corner version.
  • Design C's expanded width: hover:w-[170px] must fit the longest label — measure, do not guess, or the text clips.
  • Pair with the lift: hover:-translate-y-0.5 is on A and B; drop it for a flatter, more Swiss feel.

Gotchas — read before shipping

  • Pad the label enough that a full pill radius does not clip the first and last glyphs — px-[38px] is the floor at this font size.
  • Animate border-radius, not width, for a shape change; design C animates width only because it is genuinely changing size, and it is the one that needs overflow-hidden.
  • Design C's two labels are absolutely stacked, so the button needs an explicit height (h-14) and the glyph must be aria-hidden with the real text always present in the DOM.
  • Under motion-reduce: design C drops its transitions entirely: a reduced-motion user gets the expanded, labelled state on hover with no travel.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

border-radius transitions are universal; nothing here needs a fallback beyond Tailwind v4's own floor.

Techniques used in this demo

Search CodeFronts

Loading…