07 / 20
All 20 in 20 Tailwind CSS Animated Buttons
- 01Tailwind Neon Glow Button with Pulsing Halo
- 02Tailwind Background Slide Hover Button (Four Directions)
- 03Tailwind Ripple Effect Button with No JavaScript
- 04Tailwind Animated Border Draw Button with Staged Delays
- 05Tailwind 3D Press Effect Button with Keycap Depth
- 06Tailwind Liquid Fill Button with Animated Wave Crest
- 07Tailwind Moving Gradient CTA Button
- 08Tailwind Shine Sweep Hover Button with Gloss Streak
- 09Tailwind Jelly Bounce Button with Elastic Squash
- 10Tailwind Text Flip Button Hover with 3D Rotation
- 11Tailwind Animated CTA Hero Button with Beacon Rings & Particle Burst
- 12Tailwind Submit Button Success State with Checkmark Draw
- 13Tailwind Animated Download Button with Progress Fill
- 14Tailwind Hamburger to Close Button with aria-expanded Variants
- 15Tailwind Add to Cart Button with Flying Product Dot
- 16Tailwind Social Share Buttons with Brand Hover & Copy Link
- 17Tailwind Animated Toggle Switch with peer-checked & has-checked
- 18Tailwind Loading Spinner Inside Button with State Machine
- 19Tailwind Next & Prev Arrow Buttons with Chasing Icons
- 20Tailwind Ghost Button with Cursor-Aware Background Reveal
Tailwind Moving Gradient CTA Button
An infinite colour-cycling CTA: one oversized gradient, one background-position loop. The port is nearly a transcription — bg-[linear-gradient(...)] bg-[size:300%_300%] animate-tab07-shift — and the notable part is how the reduced-motion fallback becomes a one-utility override instead of a duplicated rule.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tab-07 w-full min-h-svh grid place-items-center bg-tab07-bg font-tab07-sans px-6 py-10">
<div class="w-[min(440px,100%)] text-center px-8 py-10 rounded-2xl bg-tab07-card border border-white/8">
<p class="text-xs tracking-[0.18em] uppercase text-tab07-acc m-0">Limited Time Offer</p>
<h2 class="mt-3 mb-3 text-[1.8rem] font-bold text-tab07-ink">Start Your Free Trial</h2>
<p class="mb-7 text-[0.9rem] leading-relaxed text-tab07-mut">14 days free, no credit card required. Cancel anytime with one click.</p>
<button type="button" class="inline-flex items-center justify-center min-h-11 px-10 text-base font-bold tracking-[0.03em] text-white rounded-xl cursor-pointer bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#f43f5e,#7c3aed)] bg-[size:300%_300%] animate-tab07-shift shadow-[0_4px_20px_oklch(0.53_0.25_295/0.4)] transition-[translate,box-shadow,filter] duration-200 hover:brightness-110 hover:-translate-y-0.5 hover:shadow-[0_6px_32px_oklch(0.53_0.25_295/0.6)] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white active:translate-y-0 active:brightness-95 motion-reduce:animate-none motion-reduce:bg-[linear-gradient(90deg,#7c3aed,#06b6d4)] motion-reduce:transition-none">Claim Your Free Trial →</button>
</div>
</section><section class="tab-07 w-full min-h-svh grid place-items-center bg-tab07-bg font-tab07-sans px-6 py-10">
<div class="w-[min(440px,100%)] text-center px-8 py-10 rounded-2xl bg-tab07-card border border-white/8">
<p class="text-xs tracking-[0.18em] uppercase text-tab07-acc m-0">Limited Time Offer</p>
<h2 class="mt-3 mb-3 text-[1.8rem] font-bold text-tab07-ink">Start Your Free Trial</h2>
<p class="mb-7 text-[0.9rem] leading-relaxed text-tab07-mut">14 days free, no credit card required. Cancel anytime with one click.</p>
<button type="button" class="inline-flex items-center justify-center min-h-11 px-10 text-base font-bold tracking-[0.03em] text-white rounded-xl cursor-pointer bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#f43f5e,#7c3aed)] bg-[size:300%_300%] animate-tab07-shift shadow-[0_4px_20px_oklch(0.53_0.25_295/0.4)] transition-[translate,box-shadow,filter] duration-200 hover:brightness-110 hover:-translate-y-0.5 hover:shadow-[0_6px_32px_oklch(0.53_0.25_295/0.6)] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white active:translate-y-0 active:brightness-95 motion-reduce:animate-none motion-reduce:bg-[linear-gradient(90deg,#7c3aed,#06b6d4)] motion-reduce:transition-none">Claim Your Free Trial →</button>
</div>
</section>@import "tailwindcss";
@theme {
--color-tab07-bg: #0a0a14;
--color-tab07-bg: oklch(0.11 0.02 275);
--color-tab07-card: #13131f;
--color-tab07-card: oklch(0.16 0.02 275);
--color-tab07-ink: #f1f5f9;
--color-tab07-ink: oklch(0.96 0.005 250);
--color-tab07-mut: #94a3b8;
--color-tab07-mut: oklch(0.72 0.03 255);
--color-tab07-acc: #a78bfa;
--color-tab07-acc: oklch(0.74 0.15 292);
--font-tab07-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tab07-shift: tab07-shift 4s ease infinite;
}
@keyframes tab07-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.tab-07 {
width: 100%;
min-height: 100svh;
}
.tab-07 ::selection {
background: var(--color-tab07-acc);
color: #14091f;
}@import "tailwindcss";
@theme {
--color-tab07-bg: #0a0a14;
--color-tab07-bg: oklch(0.11 0.02 275);
--color-tab07-card: #13131f;
--color-tab07-card: oklch(0.16 0.02 275);
--color-tab07-ink: #f1f5f9;
--color-tab07-ink: oklch(0.96 0.005 250);
--color-tab07-mut: #94a3b8;
--color-tab07-mut: oklch(0.72 0.03 255);
--color-tab07-acc: #a78bfa;
--color-tab07-acc: oklch(0.74 0.15 292);
--font-tab07-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tab07-shift: tab07-shift 4s ease infinite;
}
@keyframes tab07-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.tab-07 {
width: 100%;
min-height: 100svh;
}
.tab-07 ::selection {
background: var(--color-tab07-acc);
color: #14091f;
}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-tab07-bg: #0a0a14;
--color-tab07-bg: oklch(0.11 0.02 275);
--color-tab07-card: #13131f;
--color-tab07-card: oklch(0.16 0.02 275);
--color-tab07-ink: #f1f5f9;
--color-tab07-ink: oklch(0.96 0.005 250);
--color-tab07-mut: #94a3b8;
--color-tab07-mut: oklch(0.72 0.03 255);
--color-tab07-acc: #a78bfa;
--color-tab07-acc: oklch(0.74 0.15 292);
--font-tab07-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tab07-shift: tab07-shift 4s ease infinite;
}
@keyframes tab07-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.tab-07 {
width: 100%;
min-height: 100svh;
}
.tab-07 ::selection {
background: var(--color-tab07-acc);
color: #14091f;
}@import "tailwindcss";
@theme {
--color-tab07-bg: #0a0a14;
--color-tab07-bg: oklch(0.11 0.02 275);
--color-tab07-card: #13131f;
--color-tab07-card: oklch(0.16 0.02 275);
--color-tab07-ink: #f1f5f9;
--color-tab07-ink: oklch(0.96 0.005 250);
--color-tab07-mut: #94a3b8;
--color-tab07-mut: oklch(0.72 0.03 255);
--color-tab07-acc: #a78bfa;
--color-tab07-acc: oklch(0.74 0.15 292);
--font-tab07-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tab07-shift: tab07-shift 4s ease infinite;
}
@keyframes tab07-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.tab-07 {
width: 100%;
min-height: 100svh;
}
.tab-07 ::selection {
background: var(--color-tab07-acc);
color: #14091f;
}<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 gradient stops stay literal hex inside an arbitrary utility rather than becoming four
@themecolours. A four-stop loop is one composite decoration, not four reusable design tokens — promoting them would imply they are independently meaningful. bg-[size:300%_300%]is the arbitrary form ofbackground-size;bg-size-*does not exist because background sizing is not a design scale.- UI change from the CSS original: a white
focus-visiblering with 4px offset, which survives against every phase of the moving gradient.
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 Moving Gradient CTA Button
Source: https://codefronts.com/motion/tailwind-css-animated-buttons/tailwind-moving-gradient-cta-button/
An infinite colour-cycling CTA: one oversized gradient, one background-position loop. The port is nearly a transcription — bg-[linear-gradient(...)] bg-[size:300%_300%] animate-tab07-shift — and the notable part is how the reduced-motion fallback becomes a one-utility override instead of a duplicated rule.
## HTML
```html
<section class="tab-07 w-full min-h-svh grid place-items-center bg-tab07-bg font-tab07-sans px-6 py-10">
<div class="w-[min(440px,100%)] text-center px-8 py-10 rounded-2xl bg-tab07-card border border-white/8">
<p class="text-xs tracking-[0.18em] uppercase text-tab07-acc m-0">Limited Time Offer</p>
<h2 class="mt-3 mb-3 text-[1.8rem] font-bold text-tab07-ink">Start Your Free Trial</h2>
<p class="mb-7 text-[0.9rem] leading-relaxed text-tab07-mut">14 days free, no credit card required. Cancel anytime with one click.</p>
<button type="button" class="inline-flex items-center justify-center min-h-11 px-10 text-base font-bold tracking-[0.03em] text-white rounded-xl cursor-pointer bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#f43f5e,#7c3aed)] bg-[size:300%_300%] animate-tab07-shift shadow-[0_4px_20px_oklch(0.53_0.25_295/0.4)] transition-[translate,box-shadow,filter] duration-200 hover:brightness-110 hover:-translate-y-0.5 hover:shadow-[0_6px_32px_oklch(0.53_0.25_295/0.6)] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white active:translate-y-0 active:brightness-95 motion-reduce:animate-none motion-reduce:bg-[linear-gradient(90deg,#7c3aed,#06b6d4)] motion-reduce:transition-none">Claim Your Free Trial →</button>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tab07-bg: #0a0a14;
--color-tab07-bg: oklch(0.11 0.02 275);
--color-tab07-card: #13131f;
--color-tab07-card: oklch(0.16 0.02 275);
--color-tab07-ink: #f1f5f9;
--color-tab07-ink: oklch(0.96 0.005 250);
--color-tab07-mut: #94a3b8;
--color-tab07-mut: oklch(0.72 0.03 255);
--color-tab07-acc: #a78bfa;
--color-tab07-acc: oklch(0.74 0.15 292);
--font-tab07-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tab07-shift: tab07-shift 4s ease infinite;
}
@keyframes tab07-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.tab-07 {
width: 100%;
min-height: 100svh;
}
.tab-07 ::selection {
background: var(--color-tab07-acc);
color: #14091f;
}
```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 Moving Gradient CTA Button
Source: https://codefronts.com/motion/tailwind-css-animated-buttons/tailwind-moving-gradient-cta-button/
An infinite colour-cycling CTA: one oversized gradient, one background-position loop. The port is nearly a transcription — bg-[linear-gradient(...)] bg-[size:300%_300%] animate-tab07-shift — and the notable part is how the reduced-motion fallback becomes a one-utility override instead of a duplicated rule.
## HTML
```html
<section class="tab-07 w-full min-h-svh grid place-items-center bg-tab07-bg font-tab07-sans px-6 py-10">
<div class="w-[min(440px,100%)] text-center px-8 py-10 rounded-2xl bg-tab07-card border border-white/8">
<p class="text-xs tracking-[0.18em] uppercase text-tab07-acc m-0">Limited Time Offer</p>
<h2 class="mt-3 mb-3 text-[1.8rem] font-bold text-tab07-ink">Start Your Free Trial</h2>
<p class="mb-7 text-[0.9rem] leading-relaxed text-tab07-mut">14 days free, no credit card required. Cancel anytime with one click.</p>
<button type="button" class="inline-flex items-center justify-center min-h-11 px-10 text-base font-bold tracking-[0.03em] text-white rounded-xl cursor-pointer bg-[linear-gradient(90deg,#7c3aed,#06b6d4,#f43f5e,#7c3aed)] bg-[size:300%_300%] animate-tab07-shift shadow-[0_4px_20px_oklch(0.53_0.25_295/0.4)] transition-[translate,box-shadow,filter] duration-200 hover:brightness-110 hover:-translate-y-0.5 hover:shadow-[0_6px_32px_oklch(0.53_0.25_295/0.6)] focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white active:translate-y-0 active:brightness-95 motion-reduce:animate-none motion-reduce:bg-[linear-gradient(90deg,#7c3aed,#06b6d4)] motion-reduce:transition-none">Claim Your Free Trial →</button>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tab07-bg: #0a0a14;
--color-tab07-bg: oklch(0.11 0.02 275);
--color-tab07-card: #13131f;
--color-tab07-card: oklch(0.16 0.02 275);
--color-tab07-ink: #f1f5f9;
--color-tab07-ink: oklch(0.96 0.005 250);
--color-tab07-mut: #94a3b8;
--color-tab07-mut: oklch(0.72 0.03 255);
--color-tab07-acc: #a78bfa;
--color-tab07-acc: oklch(0.74 0.15 292);
--font-tab07-sans: 'Space Grotesk', system-ui, sans-serif;
--animate-tab07-shift: tab07-shift 4s ease infinite;
}
@keyframes tab07-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.tab-07 {
width: 100%;
min-height: 100svh;
}
.tab-07 ::selection {
background: var(--color-tab07-acc);
color: #14091f;
}
```How this works
The gradient is three times the button. bg-[size:300%_300%] means each background-position reveals a different slice, and the keyframe walks from 0% 50% to 100% 50% and back. First and last colour stops match, so the loop has no visible seam.
Two motions coexist. The infinite gradient animation and the discrete hover lift touch different properties, so they compose without fighting: animate-tab07-shift owns background-position, the transition owns translate and box-shadow.
Reduced motion substitutes, not subtracts. motion-reduce: kills the animation and swaps in a two-stop gradient in one place, on the element. The CSS version needed a whole duplicate rule inside a media block.
Make it yours
- Repalette by editing the gradient stops (
#f97316, #ec4899, #8b5cf6for a sunset) — keep the first and last identical. - Cycle speed lives in the token:
4sdefault,2senergetic,8sambient. - Freeze on hover for a "snapshot" feel with
hover:[animation-play-state:paused].
Gotchas — read before shipping
background-positionis not reliably composited — an always-running gradient costs power on battery devices. Pause it off-screen with anIntersectionObserverin production.- Mismatched end stops produce a visible jump once per loop; it is the single most common bug in this technique.
- Do not add
transition-allhere. It would tweenbackground-positionagainst the animation and produce a stutter.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Background-position animation is universally supported; the floor is Tailwind v4's generated sheet.