36 Tailwind CSS Button Hover Effects
07 / 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 Infinite Sliding Kinetic Marquee Button

A kinetic editorial CTA that trades a static label for a continuously scrolling marquee on hover — the phrase repeats and slides endlessly across the pill. The port's real work is accessibility: the scrolling copies are aria-hidden decoration and the accessible name comes from aria-label, so what a screen reader hears never moves.

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-07-group w-full min-h-svh flex flex-wrap">
<section class="tbh-07a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh07-sans bg-tbh07a-stage" aria-label="Kinetic marquee button">
  <button type="button" aria-label="Book tickets" class="group/btn relative overflow-hidden w-[230px] h-[60px] cursor-pointer border-0 rounded-full text-base font-extrabold tracking-[0.04em] text-white bg-tbh07a-acc focus-visible:outline-3 focus-visible:outline-tbh07a-acc focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute inset-0 grid place-items-center transition-opacity duration-200 group-hover/btn:opacity-0 group-focus-visible/btn:opacity-0 motion-reduce:group-hover/btn:opacity-100 motion-reduce:group-focus-visible/btn:opacity-100">Book tickets</span>
    <span aria-hidden="true" class="absolute inset-0 flex items-center gap-[34px] pl-[34px] whitespace-nowrap opacity-0 transition-opacity duration-200 group-hover/btn:opacity-100 group-hover/btn:animate-tbh07a-scroll group-focus-visible/btn:opacity-100 group-focus-visible/btn:animate-tbh07a-scroll motion-reduce:group-hover/btn:animate-none motion-reduce:group-hover/btn:opacity-0 motion-reduce:group-focus-visible/btn:animate-none motion-reduce:group-focus-visible/btn:opacity-0">
      <span>Book tickets</span><span>Book tickets</span><span>Book tickets</span><span>Book tickets</span>
    </span>
  </button>
</section>
<section class="tbh-07b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh07-sans bg-tbh07b-stage" aria-label="Vertical marquee button">
  <button type="button" aria-label="Shop the drop" class="group/btn relative overflow-hidden w-[220px] h-[58px] cursor-pointer border-0 rounded-xl text-base font-extrabold text-white bg-tbh07b-acc focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute inset-0 flex flex-col group-hover/btn:animate-tbh07b-roll group-focus-visible/btn:animate-tbh07b-roll motion-reduce:group-hover/btn:animate-none motion-reduce:group-focus-visible/btn:animate-none">
      <span class="grid place-items-center h-[58px] flex-none">Shop the drop</span>
      <span class="grid place-items-center h-[58px] flex-none">Shop the drop</span>
    </span>
  </button>
</section>
</div>
@import "tailwindcss";

@theme {
  --color-tbh07a-acc: #c8344a;
  --color-tbh07a-acc: oklch(0.55 0.2 15);
  --color-tbh07a-stage: #faf7f2;
  --color-tbh07a-stage: oklch(0.97 0.008 80);
  --color-tbh07b-acc: #6e5ad8;
  --color-tbh07b-acc: oklch(0.55 0.18 285);
  --color-tbh07b-stage: #0e0b1a;
  --color-tbh07b-stage: oklch(0.15 0.03 285);
  --font-tbh07-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh07a-scroll: tbh07a-scroll 6s linear infinite;
  --animate-tbh07b-roll: tbh07b-roll 1.6s linear infinite;
}
/* Stays CSS: the two loop keyframes. Both write the discrete translate property, so they
   cannot collide with a translate-* utility added to the same track later. */

@keyframes tbh07a-scroll {
  from {
    translate: 0 0;
  }

  to {
    translate: -50% 0;
  }
}

@keyframes tbh07b-roll {
  from {
    translate: 0 0;
  }

  to {
    translate: 0 -58px;
  }
}

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

.tbh-07a,
.tbh-07b {
  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-tbh07a-acc: #c8344a;
  --color-tbh07a-acc: oklch(0.55 0.2 15);
  --color-tbh07a-stage: #faf7f2;
  --color-tbh07a-stage: oklch(0.97 0.008 80);
  --color-tbh07b-acc: #6e5ad8;
  --color-tbh07b-acc: oklch(0.55 0.18 285);
  --color-tbh07b-stage: #0e0b1a;
  --color-tbh07b-stage: oklch(0.15 0.03 285);
  --font-tbh07-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh07a-scroll: tbh07a-scroll 6s linear infinite;
  --animate-tbh07b-roll: tbh07b-roll 1.6s linear infinite;
}
/* Stays CSS: the two loop keyframes. Both write the discrete translate property, so they
   cannot collide with a translate-* utility added to the same track later. */

@keyframes tbh07a-scroll {
  from {
    translate: 0 0;
  }

  to {
    translate: -50% 0;
  }
}

@keyframes tbh07b-roll {
  from {
    translate: 0 0;
  }

  to {
    translate: 0 -58px;
  }
}

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

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

  • Four .btn:hover .x selectors become group-hover/btn: runs on the two layers, and the animation is applied where it is triggered — which matters here because the track must be animated ONLY while hovered, and that fact is now visible rather than inferred.
  • The keyframe distance (-50%, -58px) still has to match the markup's copy count and row height. No variant can enforce that; it is the one coupling the port does not remove, and the gotchas say so.
  • UI change from the CSS original: design B now mirrors the roll on focus-visible: and both designs' reduced-motion fallbacks return the button to its resting label instead of leaving a frozen mid-scroll track.
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 Infinite Sliding Kinetic Marquee Button
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-infinite-sliding-kinetic-marquee-button/

A kinetic editorial CTA that trades a static label for a continuously scrolling marquee on hover &mdash; the phrase repeats and slides endlessly across the pill. The port's real work is accessibility: the scrolling copies are aria-hidden decoration and the accessible name comes from aria-label, so what a screen reader hears never moves.
## HTML
```html
<div class="tbh-07-group w-full min-h-svh flex flex-wrap">
<section class="tbh-07a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh07-sans bg-tbh07a-stage" aria-label="Kinetic marquee button">
  <button type="button" aria-label="Book tickets" class="group/btn relative overflow-hidden w-[230px] h-[60px] cursor-pointer border-0 rounded-full text-base font-extrabold tracking-[0.04em] text-white bg-tbh07a-acc focus-visible:outline-3 focus-visible:outline-tbh07a-acc focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute inset-0 grid place-items-center transition-opacity duration-200 group-hover/btn:opacity-0 group-focus-visible/btn:opacity-0 motion-reduce:group-hover/btn:opacity-100 motion-reduce:group-focus-visible/btn:opacity-100">Book tickets</span>
    <span aria-hidden="true" class="absolute inset-0 flex items-center gap-[34px] pl-[34px] whitespace-nowrap opacity-0 transition-opacity duration-200 group-hover/btn:opacity-100 group-hover/btn:animate-tbh07a-scroll group-focus-visible/btn:opacity-100 group-focus-visible/btn:animate-tbh07a-scroll motion-reduce:group-hover/btn:animate-none motion-reduce:group-hover/btn:opacity-0 motion-reduce:group-focus-visible/btn:animate-none motion-reduce:group-focus-visible/btn:opacity-0">
      <span>Book tickets</span><span>Book tickets</span><span>Book tickets</span><span>Book tickets</span>
    </span>
  </button>
</section>
<section class="tbh-07b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh07-sans bg-tbh07b-stage" aria-label="Vertical marquee button">
  <button type="button" aria-label="Shop the drop" class="group/btn relative overflow-hidden w-[220px] h-[58px] cursor-pointer border-0 rounded-xl text-base font-extrabold text-white bg-tbh07b-acc focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px]">
    <span aria-hidden="true" class="absolute inset-0 flex flex-col group-hover/btn:animate-tbh07b-roll group-focus-visible/btn:animate-tbh07b-roll motion-reduce:group-hover/btn:animate-none motion-reduce:group-focus-visible/btn:animate-none">
      <span class="grid place-items-center h-[58px] flex-none">Shop the drop</span>
      <span class="grid place-items-center h-[58px] flex-none">Shop the drop</span>
    </span>
  </button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tbh07a-acc: #c8344a;
  --color-tbh07a-acc: oklch(0.55 0.2 15);
  --color-tbh07a-stage: #faf7f2;
  --color-tbh07a-stage: oklch(0.97 0.008 80);
  --color-tbh07b-acc: #6e5ad8;
  --color-tbh07b-acc: oklch(0.55 0.18 285);
  --color-tbh07b-stage: #0e0b1a;
  --color-tbh07b-stage: oklch(0.15 0.03 285);
  --font-tbh07-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tbh07a-scroll: tbh07a-scroll 6s linear infinite;
  --animate-tbh07b-roll: tbh07b-roll 1.6s linear infinite;
}
/* Stays CSS: the two loop keyframes. Both write the discrete translate property, so they
   cannot collide with a translate-* utility added to the same track later. */

@keyframes tbh07a-scroll {
  from {
    translate: 0 0;
  }

  to {
    translate: -50% 0;
  }
}

@keyframes tbh07b-roll {
  from {
    translate: 0 0;
  }

  to {
    translate: 0 -58px;
  }
}

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

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

How this works

Seamlessness is arithmetic, not easing. The track holds four copies and the keyframe travels exactly -50%, so frame 1 and the final frame are pixel-identical and the loop has no seam. Halve the copies or change the distance and the jump becomes visible immediately.

Two layers, one cross-fade. The static label and the scrolling track both sit absolute inset-0; hover fades one out and the other in, then starts the animation. Because the track is only animated while hovered, an idle page of these buttons costs nothing.

Design B rolls vertically. Two stacked copies of the label in a column, translating by exactly one button height (-58px) — the same seam arithmetic on the other axis, and the pattern behind every 'Add to cart → Added' roll.

Make it yours

  • Speed: --animate-tbh07a-scroll's 6s. Below ~3s the copy becomes unreadable.
  • Copy count: keep it even, and keep the keyframe at -50%; those two facts are one decision.
  • Direction: negate the keyframe translate for a right-to-left run.
  • Gap rhythm: gap-[34px] pl-[34px] — the padding must equal the gap or the first repeat sits closer than the rest.

Gotchas — read before shipping

  • The scrolling copies MUST be aria-hidden and the button MUST carry aria-label, or a screen reader announces the phrase four times.
  • overflow-hidden is load-bearing; without it the track escapes the pill and overlaps the page.
  • An odd number of copies cannot loop seamlessly at -50%, whatever the duration.
  • Design B's column children need flex-none and an explicit h-[58px], or flex shrinks them and the roll distance stops matching the keyframe.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Flexbox and keyframes are universal; with CSS unavailable the static label still renders as the button's text content.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Plain CSSno Tailwind surface

Search CodeFronts

Loading…