36 Tailwind CSS Button Hover Effects
15 / 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 Liquid Wave Fill Button Hover Effect

A CTA that fills like a glass of water: on hover a coloured liquid rises from the bottom with a scalloped wave crest that sways — the bottom-up fill, distinct from entry 13's centre-out blob. The crest is a repeating radial-gradient, which is the trick worth stealing from this one.

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-15-group w-full min-h-svh flex flex-wrap">
<section class="tbh-15a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh15-sans bg-tbh15a-stage" aria-label="Liquid wave fill button">
  <button type="button" class="group/btn relative isolate overflow-hidden cursor-pointer rounded-xl border-2 border-tbh15a-liquid px-11 py-[18px] text-base font-extrabold text-tbh15a-liquid bg-transparent transition-colors duration-[350ms] delay-150 hover:text-white focus-visible:text-white focus-visible:outline-3 focus-visible:outline-tbh15a-liquid focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute -left-1/2 top-full w-[200%] h-full z-[1] bg-tbh15a-liquid translate-y-[22px] transition-[translate] duration-[550ms] ease-[cubic-bezier(.4,0,.2,1)] before:content-[''] before:absolute before:left-0 before:bottom-full before:w-full before:h-[22px] before:bg-[radial-gradient(circle_at_25%_0,transparent_12px,var(--color-tbh15a-liquid)_13px)] before:bg-[length:44px_22px] before:bg-repeat-x group-hover/btn:-translate-y-full group-hover/btn:animate-tbh15a-sway group-focus-visible/btn:-translate-y-full group-focus-visible/btn:animate-tbh15a-sway motion-reduce:transition-none motion-reduce:group-hover/btn:animate-none motion-reduce:group-focus-visible/btn:animate-none"></span>
    <span class="relative z-[2]">Download</span>
  </button>
</section>
<section class="tbh-15b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh15-sans bg-tbh15b-stage" aria-label="Tilted flood button">
  <button type="button" class="group/btn relative isolate overflow-hidden cursor-pointer rounded-full border-2 border-tbh15b-liquid px-[46px] py-[18px] text-base font-extrabold text-tbh15b-liquid bg-transparent transition-colors duration-300 delay-[120ms] hover:text-tbh15b-ink focus-visible:text-tbh15b-ink focus-visible:outline-3 focus-visible:outline-tbh15b-liquid focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute -left-[10%] bottom-0 w-[120%] h-[180%] z-0 origin-top bg-tbh15b-liquid [rotate:6deg] translate-y-[120%] transition-[translate,rotate] duration-500 ease-[cubic-bezier(.5,0,.2,1)] group-hover/btn:[rotate:0deg] group-hover/btn:translate-y-0 group-focus-visible/btn:[rotate:0deg] group-focus-visible/btn:translate-y-0 motion-reduce:duration-[250ms]"></span>
    <span class="relative z-[1]">Install now</span>
  </button>
</section>
</div>
@import "tailwindcss";

@theme {
  --color-tbh15a-liquid: #4f86e0;
  --color-tbh15a-liquid: oklch(0.6 0.18 235);
  --color-tbh15a-stage: #0b1020;
  --color-tbh15a-stage: oklch(0.14 0.03 265);
  --color-tbh15b-liquid: #6fd99a;
  --color-tbh15b-liquid: oklch(0.7 0.17 150);
  --color-tbh15b-ink: #04180d;
  --color-tbh15b-ink: oklch(0.2 0.05 150);
  --color-tbh15b-stage: #08160e;
  --color-tbh15b-stage: oklch(0.15 0.02 150);
  --font-tbh15-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh15a-sway: tbh15a-sway 1.6s ease-in-out infinite;
}
/* Stays CSS: the sway keyframe. Ported from the original's margin-left animation to the
   discrete translate property — same motion, no layout work per frame. */

@keyframes tbh15a-sway {
  0%,
    100% {
    translate: 0 -100%;
  }

  50% {
    translate: 22px -100%;
  }
}

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

.tbh-15a,
.tbh-15b {
  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-tbh15a-liquid: #4f86e0;
  --color-tbh15a-liquid: oklch(0.6 0.18 235);
  --color-tbh15a-stage: #0b1020;
  --color-tbh15a-stage: oklch(0.14 0.03 265);
  --color-tbh15b-liquid: #6fd99a;
  --color-tbh15b-liquid: oklch(0.7 0.17 150);
  --color-tbh15b-ink: #04180d;
  --color-tbh15b-ink: oklch(0.2 0.05 150);
  --color-tbh15b-stage: #08160e;
  --color-tbh15b-stage: oklch(0.15 0.02 150);
  --font-tbh15-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh15a-sway: tbh15a-sway 1.6s ease-in-out infinite;
}
/* Stays CSS: the sway keyframe. Ported from the original's margin-left animation to the
   discrete translate property — same motion, no layout work per frame. */

@keyframes tbh15a-sway {
  0%,
    100% {
    translate: 0 -100%;
  }

  50% {
    translate: 22px -100%;
  }
}

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

.tbh-15a,
.tbh-15b {
  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 crest gradient is the entry's real content, and it ports verbatim into before:bg-[radial-gradient(...)] with bg-[length:44px_22px] bg-repeat-x — two utilities for what most implementations reach for an SVG to do.
  • The sway keyframe changed technique in the port: the original animated margin-left, which relayouts the layer every frame. Writing it as translate composites instead, and because the keyframe must hold the risen -100% Y offset, it states both axes explicitly.
  • UI change from the CSS original: both designs now rise on group-focus-visible/btn: as well as hover, and design A's reduced-motion path fills without the sway rather than dropping the effect.
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 Liquid Wave Fill Button Hover Effect
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-liquid-wave-fill-button-hover-effect/

A CTA that fills like a glass of water: on hover a coloured liquid rises from the bottom with a scalloped wave crest that sways &mdash; the bottom-up fill, distinct from entry 13's centre-out blob. The crest is a repeating radial-gradient, which is the trick worth stealing from this one.
## HTML
```html
<div class="tbh-15-group w-full min-h-svh flex flex-wrap">
<section class="tbh-15a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh15-sans bg-tbh15a-stage" aria-label="Liquid wave fill button">
  <button type="button" class="group/btn relative isolate overflow-hidden cursor-pointer rounded-xl border-2 border-tbh15a-liquid px-11 py-[18px] text-base font-extrabold text-tbh15a-liquid bg-transparent transition-colors duration-[350ms] delay-150 hover:text-white focus-visible:text-white focus-visible:outline-3 focus-visible:outline-tbh15a-liquid focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute -left-1/2 top-full w-[200%] h-full z-[1] bg-tbh15a-liquid translate-y-[22px] transition-[translate] duration-[550ms] ease-[cubic-bezier(.4,0,.2,1)] before:content-[''] before:absolute before:left-0 before:bottom-full before:w-full before:h-[22px] before:bg-[radial-gradient(circle_at_25%_0,transparent_12px,var(--color-tbh15a-liquid)_13px)] before:bg-[length:44px_22px] before:bg-repeat-x group-hover/btn:-translate-y-full group-hover/btn:animate-tbh15a-sway group-focus-visible/btn:-translate-y-full group-focus-visible/btn:animate-tbh15a-sway motion-reduce:transition-none motion-reduce:group-hover/btn:animate-none motion-reduce:group-focus-visible/btn:animate-none"></span>
    <span class="relative z-[2]">Download</span>
  </button>
</section>
<section class="tbh-15b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh15-sans bg-tbh15b-stage" aria-label="Tilted flood button">
  <button type="button" class="group/btn relative isolate overflow-hidden cursor-pointer rounded-full border-2 border-tbh15b-liquid px-[46px] py-[18px] text-base font-extrabold text-tbh15b-liquid bg-transparent transition-colors duration-300 delay-[120ms] hover:text-tbh15b-ink focus-visible:text-tbh15b-ink focus-visible:outline-3 focus-visible:outline-tbh15b-liquid focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute -left-[10%] bottom-0 w-[120%] h-[180%] z-0 origin-top bg-tbh15b-liquid [rotate:6deg] translate-y-[120%] transition-[translate,rotate] duration-500 ease-[cubic-bezier(.5,0,.2,1)] group-hover/btn:[rotate:0deg] group-hover/btn:translate-y-0 group-focus-visible/btn:[rotate:0deg] group-focus-visible/btn:translate-y-0 motion-reduce:duration-[250ms]"></span>
    <span class="relative z-[1]">Install now</span>
  </button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tbh15a-liquid: #4f86e0;
  --color-tbh15a-liquid: oklch(0.6 0.18 235);
  --color-tbh15a-stage: #0b1020;
  --color-tbh15a-stage: oklch(0.14 0.03 265);
  --color-tbh15b-liquid: #6fd99a;
  --color-tbh15b-liquid: oklch(0.7 0.17 150);
  --color-tbh15b-ink: #04180d;
  --color-tbh15b-ink: oklch(0.2 0.05 150);
  --color-tbh15b-stage: #08160e;
  --color-tbh15b-stage: oklch(0.15 0.02 150);
  --font-tbh15-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh15a-sway: tbh15a-sway 1.6s ease-in-out infinite;
}
/* Stays CSS: the sway keyframe. Ported from the original's margin-left animation to the
   discrete translate property — same motion, no layout work per frame. */

@keyframes tbh15a-sway {
  0%,
    100% {
    translate: 0 -100%;
  }

  50% {
    translate: 22px -100%;
  }
}

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

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

How this works

The crest is one gradient. A circle punched out of a solid colour, repeated every 44px, gives a scalloped waterline — no SVG, no mask, no image request. It sits on a before: layer at the top edge of the liquid, so it rises with it.

Rise, then sway. The lift is a transition (550ms, decelerating) and the sway is an animation applied only in the hovered state. Separating them is what keeps the water from wobbling while it is still climbing.

Design B settles two properties at once. A layer taller than the button, rotated 6deg and pushed below, arrives by returning rotate to 0 and translate to 0 — and because v4 keeps those separate, the resting tilt and the resting offset are independent values rather than one compound transform to keep in sync.

Make it yours

  • Wave scale: the gradient's 12px/13px radii and the 44px_22px tile — larger tiles read as ocean, smaller as fizz.
  • Fill speed: duration-[550ms] on the liquid layer.
  • Sway amplitude: the 22px in the sway keyframe; more reads as choppier water.
  • Partial fill: change the hover target from -translate-y-full to -translate-y-[60%] and the button becomes a progress indicator.

Gotchas — read before shipping

  • overflow-hidden clips the liquid; without it the layer paints across the page as it rises.
  • The liquid layer must be wider than the button (-left-1/2 w-[200%]) so the sway never exposes a dry edge.
  • The label must invert on hover and sit above the liquid (relative z-[2]) — the crest is opaque and will swallow text that shares its stacking level.
  • The sway animates translate, not margin-left as the CSS original did — a margin animation relayouts the wave every frame for no visual gain.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Repeating radial gradients and transforms are universal; with CSS unavailable each button is a plain outlined CTA.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Plain CSSno Tailwind surface

Search CodeFronts

Loading…