31 / 36
All 36 in 36 Tailwind CSS Button Hover Effects
- 01Tailwind Magnetic Ripple Attraction Button Hover Effect
- 02Tailwind Cyberpunk Holographic Glitch Grid Button
- 03Tailwind Frosted Glassmorphism Shimmer Glow Button
- 04Tailwind Organic Blob Morph Button Hover Effect
- 05Tailwind Dual-Line Intersection Border Draw Button
- 06Tailwind Isometric Tactile 3D Depress Button
- 07Tailwind Infinite Sliding Kinetic Marquee Button
- 08Tailwind Chroma Conic Gradient Border Spin Button
- 09Tailwind Minimalist Border & Outline Drawing Hover Effects
- 10Tailwind Modern 3D Skeuomorphic Button Press Effects
- 11Tailwind Neo-Brutalist & Cyberpunk Button Glow Effects
- 12Tailwind Sliding Background Color Wipe Button Effects
- 13Tailwind Liquid Fill & Organic Morphing Button Effects
- 14Tailwind Kinetic Text Flip & Icon Reveal Button Effects
- 15Tailwind Liquid Wave Fill Button Hover Effect
- 16Tailwind Magnetic Border Drift Button
- 17Tailwind Glitch Slice Button Hover Effect
- 18Tailwind Neon Pulse Glow Button Hover Effect
- 19Tailwind Split Reveal Curtain Button Effect
- 20Tailwind Diagonal Shutter Sweep Button Effect
- 21Tailwind Elastic Lift Spring Button Hover Effect
- 22Tailwind Center Underline Draw Link Button Effects
- 23Tailwind 3D Flip Card Button Hover Effect
- 24Tailwind Particle Burst Confetti Button Effect
- 25Tailwind Slide Doors Closing Panel Button Effect
- 26Tailwind Typewriter Retype Terminal Button Effect
- 27Tailwind Hard Shadow Shift Flat Button Effect
- 28Tailwind Material Ripple Wave Button Effect
- 29Tailwind Rainbow Gradient Border Spin Button
- 30Tailwind Morph Shape Silhouette Button Effects
- 31Tailwind Icon Slide In Directional Button Effect
- 32Tailwind Cursor Spotlight Glow Button
- 33Tailwind Stagger Fill Equaliser Button Effect
- 34Tailwind Sunburst Expand Radiant Button Effect
- 35Tailwind 3D Press Plunger Key Button Effect
- 36Tailwind Add-to-Cart Liquid Glass Ripple Button
Tailwind Icon Slide In Directional Button Effect
A directional CTA where the label nudges aside and an arrow slides in from outside the edge on hover — a purposeful 'forward' cue for Next and Continue actions. The icon animates width from 0, which is the one honest way to make it claim space without the label jumping.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tbh-31-group w-full min-h-svh flex flex-wrap">
<section class="tbh-31a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31a-stage" aria-label="Icon slide in button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31a-acc focus-visible:outline-3 focus-visible:outline-tbh31a-acc focus-visible:outline-offset-4">
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:-translate-x-1 group-focus-visible/btn:-translate-x-1 motion-reduce:transition-none">Continue</span>
<span aria-hidden="true" class="w-0 ml-0 overflow-hidden text-lg opacity-0 -translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:ml-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:ml-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">→</span>
</button>
</section>
<section class="tbh-31b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31b-stage" aria-label="Icon swap button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31b-acc focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4">
<span aria-hidden="true" class="w-0 mr-0 overflow-hidden text-lg opacity-0 translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:mr-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:mr-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">↓</span>
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:translate-x-1 group-focus-visible/btn:translate-x-1 motion-reduce:transition-none">Save file</span>
</button>
</section>
</div><div class="tbh-31-group w-full min-h-svh flex flex-wrap">
<section class="tbh-31a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31a-stage" aria-label="Icon slide in button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31a-acc focus-visible:outline-3 focus-visible:outline-tbh31a-acc focus-visible:outline-offset-4">
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:-translate-x-1 group-focus-visible/btn:-translate-x-1 motion-reduce:transition-none">Continue</span>
<span aria-hidden="true" class="w-0 ml-0 overflow-hidden text-lg opacity-0 -translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:ml-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:ml-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">→</span>
</button>
</section>
<section class="tbh-31b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31b-stage" aria-label="Icon swap button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31b-acc focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4">
<span aria-hidden="true" class="w-0 mr-0 overflow-hidden text-lg opacity-0 translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:mr-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:mr-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">↓</span>
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:translate-x-1 group-focus-visible/btn:translate-x-1 motion-reduce:transition-none">Save file</span>
</button>
</section>
</div>@import "tailwindcss";
@theme {
--color-tbh31a-acc: #6154c8;
--color-tbh31a-acc: oklch(0.55 0.17 275);
--color-tbh31a-stage: #eef0f6;
--color-tbh31a-stage: oklch(0.95 0.008 275);
--color-tbh31b-acc: #3d94a0;
--color-tbh31b-acc: oklch(0.58 0.15 200);
--color-tbh31b-stage: #0a1618;
--color-tbh31b-stage: oklch(0.15 0.02 200);
--font-tbh31-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: a zero-width icon growing into a flex row. */
.tbh-31-group {
width: 100%;
min-height: 100svh;
}
.tbh-31a,
.tbh-31b {
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbh31a-acc: #6154c8;
--color-tbh31a-acc: oklch(0.55 0.17 275);
--color-tbh31a-stage: #eef0f6;
--color-tbh31a-stage: oklch(0.95 0.008 275);
--color-tbh31b-acc: #3d94a0;
--color-tbh31b-acc: oklch(0.58 0.15 200);
--color-tbh31b-stage: #0a1618;
--color-tbh31b-stage: oklch(0.15 0.02 200);
--font-tbh31-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: a zero-width icon growing into a flex row. */
.tbh-31-group {
width: 100%;
min-height: 100svh;
}
.tbh-31a,
.tbh-31b {
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<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.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tbh31a-acc: #6154c8;
--color-tbh31a-acc: oklch(0.55 0.17 275);
--color-tbh31a-stage: #eef0f6;
--color-tbh31a-stage: oklch(0.95 0.008 275);
--color-tbh31b-acc: #3d94a0;
--color-tbh31b-acc: oklch(0.58 0.15 200);
--color-tbh31b-stage: #0a1618;
--color-tbh31b-stage: oklch(0.15 0.02 200);
--font-tbh31-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: a zero-width icon growing into a flex row. */
.tbh-31-group {
width: 100%;
min-height: 100svh;
}
.tbh-31a,
.tbh-31b {
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbh31a-acc: #6154c8;
--color-tbh31a-acc: oklch(0.55 0.17 275);
--color-tbh31a-stage: #eef0f6;
--color-tbh31a-stage: oklch(0.95 0.008 275);
--color-tbh31b-acc: #3d94a0;
--color-tbh31b-acc: oklch(0.58 0.15 200);
--color-tbh31b-stage: #0a1618;
--color-tbh31b-stage: oklch(0.15 0.02 200);
--font-tbh31-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: a zero-width icon growing into a flex row. */
.tbh-31-group {
width: 100%;
min-height: 100svh;
}
.tbh-31a,
.tbh-31b {
min-height: 100svh;
}<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">
<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 transition list is the interesting part of this port:
transition-[width,margin,translate,opacity]states outright that four properties must move together, where the CSS original's shorthand made the same claim in a form nobody reads carefully. - Splitting
translatefrom the width growth means the icon's parked offset survives edits to its size — in CSS both lived in onetransform/widthpair that had to be kept consistent by hand. - UI change from the CSS original: both designs mirror the slide on
group-focus-visible/btn:, and reduced motion keeps an opacity-only reveal so the icon still appears rather than vanishing from the interaction.
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 Icon Slide In Directional Button Effect
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-icon-slide-in-directional-button-effect/
A directional CTA where the label nudges aside and an arrow slides in from outside the edge on hover — a purposeful 'forward' cue for Next and Continue actions. The icon animates width from 0, which is the one honest way to make it claim space without the label jumping.
## HTML
```html
<div class="tbh-31-group w-full min-h-svh flex flex-wrap">
<section class="tbh-31a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31a-stage" aria-label="Icon slide in button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31a-acc focus-visible:outline-3 focus-visible:outline-tbh31a-acc focus-visible:outline-offset-4">
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:-translate-x-1 group-focus-visible/btn:-translate-x-1 motion-reduce:transition-none">Continue</span>
<span aria-hidden="true" class="w-0 ml-0 overflow-hidden text-lg opacity-0 -translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:ml-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:ml-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">→</span>
</button>
</section>
<section class="tbh-31b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31b-stage" aria-label="Icon swap button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31b-acc focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4">
<span aria-hidden="true" class="w-0 mr-0 overflow-hidden text-lg opacity-0 translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:mr-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:mr-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">↓</span>
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:translate-x-1 group-focus-visible/btn:translate-x-1 motion-reduce:transition-none">Save file</span>
</button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbh31a-acc: #6154c8;
--color-tbh31a-acc: oklch(0.55 0.17 275);
--color-tbh31a-stage: #eef0f6;
--color-tbh31a-stage: oklch(0.95 0.008 275);
--color-tbh31b-acc: #3d94a0;
--color-tbh31b-acc: oklch(0.58 0.15 200);
--color-tbh31b-stage: #0a1618;
--color-tbh31b-stage: oklch(0.15 0.02 200);
--font-tbh31-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: a zero-width icon growing into a flex row. */
.tbh-31-group {
width: 100%;
min-height: 100svh;
}
.tbh-31a,
.tbh-31b {
min-height: 100svh;
}
```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 Icon Slide In Directional Button Effect
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-icon-slide-in-directional-button-effect/
A directional CTA where the label nudges aside and an arrow slides in from outside the edge on hover — a purposeful 'forward' cue for Next and Continue actions. The icon animates width from 0, which is the one honest way to make it claim space without the label jumping.
## HTML
```html
<div class="tbh-31-group w-full min-h-svh flex flex-wrap">
<section class="tbh-31a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31a-stage" aria-label="Icon slide in button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31a-acc focus-visible:outline-3 focus-visible:outline-tbh31a-acc focus-visible:outline-offset-4">
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:-translate-x-1 group-focus-visible/btn:-translate-x-1 motion-reduce:transition-none">Continue</span>
<span aria-hidden="true" class="w-0 ml-0 overflow-hidden text-lg opacity-0 -translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:ml-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:ml-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">→</span>
</button>
</section>
<section class="tbh-31b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh31-sans bg-tbh31b-stage" aria-label="Icon swap button">
<button type="button" class="group/btn inline-flex items-center justify-center overflow-hidden cursor-pointer border-0 rounded-[10px] px-[34px] py-4 text-base font-extrabold text-white bg-tbh31b-acc focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-4">
<span aria-hidden="true" class="w-0 mr-0 overflow-hidden text-lg opacity-0 translate-x-1.5 transition-[width,margin,translate,opacity] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:w-[18px] group-hover/btn:mr-2 group-hover/btn:opacity-100 group-hover/btn:translate-x-0 group-focus-visible/btn:w-[18px] group-focus-visible/btn:mr-2 group-focus-visible/btn:opacity-100 group-focus-visible/btn:translate-x-0 motion-reduce:transition-[opacity]">↓</span>
<span class="transition-[translate] duration-300 ease-[cubic-bezier(.2,.9,.2,1)] group-hover/btn:translate-x-1 group-focus-visible/btn:translate-x-1 motion-reduce:transition-none">Save file</span>
</button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbh31a-acc: #6154c8;
--color-tbh31a-acc: oklch(0.55 0.17 275);
--color-tbh31a-stage: #eef0f6;
--color-tbh31a-stage: oklch(0.95 0.008 275);
--color-tbh31b-acc: #3d94a0;
--color-tbh31b-acc: oklch(0.58 0.15 200);
--color-tbh31b-stage: #0a1618;
--color-tbh31b-stage: oklch(0.15 0.02 200);
--font-tbh31-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Nothing stays CSS: a zero-width icon growing into a flex row. */
.tbh-31-group {
width: 100%;
min-height: 100svh;
}
.tbh-31a,
.tbh-31b {
min-height: 100svh;
}
```How this works
Width, deliberately. Every other demo in this collection avoids animating layout. This one cannot: the icon has to push the label, and a transform-only version would either overlap the text or need permanently reserved space that looks like a typo at rest. The cost is acceptable because the animating box is 18px inside an already-isolated button.
Three properties, one gesture. Opacity, width and translate all run at 300ms on the same curve. If any one is faster the icon visibly arrives in stages — which is exactly the failure the CSS original's four-property transition shorthand was guarding against, and now the grouping is stated on the element.
Design B mirrors it. The icon leads (a download arrow before 'Save file'), slides in from the left, and the label nudges right — the same utilities with the signs flipped, which is the whole difference between a 'forward' and a 'commit' cue.
Make it yours
- Icon: any glyph or inline SVG; keep
aria-hiddenand keep the resting width at 0. - Slide distance:
-translate-x-1.5resting. Larger reads as a longer approach but risks clipping againstoverflow-hidden. - Label nudge:
group-hover/btn:-translate-x-1; drop it and the icon appears to shove the text rather than join it. - Recolour through
--color-tbh31a-acc; the fill and the focus ring share it.
Gotchas — read before shipping
- Match the label and icon timings exactly (both 300ms here) or the gesture reads as two events.
- The icon must be
aria-hidden— an arrow glyph announced after the label ('Continue right arrow') is noise. overflow-hiddenon the button is what hides the parked icon; without it the glyph sits outside the button at rest.- Under
motion-reduce:only opacity transitions — the icon still appears, it just does not travel or grow.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Flexbox and transforms are universal; with CSS unavailable the label renders normally and the icon is inert.