Pure TailwindMIT licensed

Tailwind Shine Sweep Hover Button with Gloss Streak

A narrow band of light crosses the button face once per hover. The port puts the streak's whole identity — gradient, tilt, starting position — on the element as before: utilities, and its motion in one hover:before:animate-tab08-shine.

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

<section class="tab-08 w-full min-h-svh grid place-items-center bg-tab08-bg font-tab08-sans px-6 py-10">
  <div class="flex flex-col items-center gap-8">
    <p class="text-[0.78rem] tracking-[0.14em] uppercase text-tab08-mut m-0">Hover over the buttons</p>
    <div class="flex flex-wrap justify-center gap-4">
      <button type="button" class="relative overflow-hidden min-h-11 px-9 text-[0.95rem] font-bold tracking-[0.04em] text-tab08-ink bg-tab08-slate rounded-[10px] cursor-pointer transition-[translate,filter] duration-150 hover:brightness-110 hover:-translate-y-0.5 active:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab08-slate before:content-[''] before:absolute before:-top-[10%] before:-left-[20%] before:w-[60%] before:h-[120%] before:bg-[linear-gradient(105deg,transparent_30%,oklch(1_0_0/0.55)_50%,transparent_70%)] before:-skew-x-[15deg] before:-translate-x-full before:pointer-events-none hover:before:animate-tab08-shine focus-visible:before:animate-tab08-shine motion-reduce:hover:before:animate-none motion-reduce:transition-none">Pro Features</button>
      <button type="button" class="relative overflow-hidden min-h-11 px-9 text-[0.95rem] font-bold tracking-[0.04em] text-white bg-[linear-gradient(135deg,#b45309,#d97706,#fbbf24)] rounded-[10px] cursor-pointer transition-[translate,filter] duration-150 hover:brightness-110 hover:-translate-y-0.5 active:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab08-gold before:content-[''] before:absolute before:-top-[10%] before:-left-[20%] before:w-[60%] before:h-[120%] before:bg-[linear-gradient(105deg,transparent_30%,oklch(1_0_0/0.55)_50%,transparent_70%)] before:-skew-x-[15deg] before:-translate-x-full before:pointer-events-none hover:before:animate-tab08-shine focus-visible:before:animate-tab08-shine motion-reduce:hover:before:animate-none motion-reduce:transition-none">Upgrade Now</button>
      <button type="button" class="relative overflow-hidden min-h-11 px-9 text-[0.95rem] font-bold tracking-[0.04em] text-white bg-[linear-gradient(135deg,#4c1d95,#7c3aed,#a78bfa)] rounded-[10px] cursor-pointer transition-[translate,filter] duration-150 hover:brightness-110 hover:-translate-y-0.5 active:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab08-violet before:content-[''] before:absolute before:-top-[10%] before:-left-[20%] before:w-[60%] before:h-[120%] before:bg-[linear-gradient(105deg,transparent_30%,oklch(1_0_0/0.55)_50%,transparent_70%)] before:-skew-x-[15deg] before:-translate-x-full before:pointer-events-none hover:before:animate-tab08-shine focus-visible:before:animate-tab08-shine motion-reduce:hover:before:animate-none motion-reduce:transition-none">Get Premium</button>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tab08-bg: #f1f5f9;
  --color-tab08-bg: oklch(0.97 0.006 250);
  --color-tab08-mut: #64748b;
  --color-tab08-mut: oklch(0.55 0.03 255);
  --color-tab08-slate: #1e293b;
  --color-tab08-slate: oklch(0.28 0.03 258);
  --color-tab08-ink: #e2e8f0;
  --color-tab08-ink: oklch(0.92 0.01 250);
  --color-tab08-gold: #b45309;
  --color-tab08-gold: oklch(0.53 0.15 62);
  --color-tab08-violet: #4c1d95;
  --color-tab08-violet: oklch(0.36 0.2 296);
  --font-tab08-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tab08-shine: tab08-shine 0.55s ease-in-out forwards;
}

@keyframes tab08-shine {
  0% {
    translate: -100% 0;
  }

  100% {
    translate: 400% 0;
  }
}

.tab-08 {
  width: 100%;
  min-height: 100svh;
}

.tab-08 ::selection {
  background: var(--color-tab08-slate);
  color: #fff;
}

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-tab08-bg: #f1f5f9;
  --color-tab08-bg: oklch(0.97 0.006 250);
  --color-tab08-mut: #64748b;
  --color-tab08-mut: oklch(0.55 0.03 255);
  --color-tab08-slate: #1e293b;
  --color-tab08-slate: oklch(0.28 0.03 258);
  --color-tab08-ink: #e2e8f0;
  --color-tab08-ink: oklch(0.92 0.01 250);
  --color-tab08-gold: #b45309;
  --color-tab08-gold: oklch(0.53 0.15 62);
  --color-tab08-violet: #4c1d95;
  --color-tab08-violet: oklch(0.36 0.2 296);
  --font-tab08-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tab08-shine: tab08-shine 0.55s ease-in-out forwards;
}

@keyframes tab08-shine {
  0% {
    translate: -100% 0;
  }

  100% {
    translate: 400% 0;
  }
}

.tab-08 {
  width: 100%;
  min-height: 100svh;
}

.tab-08 ::selection {
  background: var(--color-tab08-slate);
  color: #fff;
}
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 keyframe animates the translate property, not transform, so it composes with the -skew-x-* utility instead of overwriting it. That is the v4-native way to mix a utility transform with a keyframed one.
  • The streak's gradient stays an arbitrary utility rather than a token: it is one decorative composite, not a reusable colour.
  • UI change from the CSS original: the sweep now also fires on focus-visible, so the premium cue is not reserved for pointer users.
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 Shine Sweep Hover Button with Gloss Streak
Source: https://codefronts.com/motion/tailwind-css-animated-buttons/tailwind-shine-sweep-hover-button/

A narrow band of light crosses the button face once per hover. The port puts the streak's whole identity &mdash; gradient, tilt, starting position &mdash; on the element as before: utilities, and its motion in one hover:before:animate-tab08-shine.
## HTML
```html
<section class="tab-08 w-full min-h-svh grid place-items-center bg-tab08-bg font-tab08-sans px-6 py-10">
  <div class="flex flex-col items-center gap-8">
    <p class="text-[0.78rem] tracking-[0.14em] uppercase text-tab08-mut m-0">Hover over the buttons</p>
    <div class="flex flex-wrap justify-center gap-4">
      <button type="button" class="relative overflow-hidden min-h-11 px-9 text-[0.95rem] font-bold tracking-[0.04em] text-tab08-ink bg-tab08-slate rounded-[10px] cursor-pointer transition-[translate,filter] duration-150 hover:brightness-110 hover:-translate-y-0.5 active:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab08-slate before:content-[''] before:absolute before:-top-[10%] before:-left-[20%] before:w-[60%] before:h-[120%] before:bg-[linear-gradient(105deg,transparent_30%,oklch(1_0_0/0.55)_50%,transparent_70%)] before:-skew-x-[15deg] before:-translate-x-full before:pointer-events-none hover:before:animate-tab08-shine focus-visible:before:animate-tab08-shine motion-reduce:hover:before:animate-none motion-reduce:transition-none">Pro Features</button>
      <button type="button" class="relative overflow-hidden min-h-11 px-9 text-[0.95rem] font-bold tracking-[0.04em] text-white bg-[linear-gradient(135deg,#b45309,#d97706,#fbbf24)] rounded-[10px] cursor-pointer transition-[translate,filter] duration-150 hover:brightness-110 hover:-translate-y-0.5 active:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab08-gold before:content-[''] before:absolute before:-top-[10%] before:-left-[20%] before:w-[60%] before:h-[120%] before:bg-[linear-gradient(105deg,transparent_30%,oklch(1_0_0/0.55)_50%,transparent_70%)] before:-skew-x-[15deg] before:-translate-x-full before:pointer-events-none hover:before:animate-tab08-shine focus-visible:before:animate-tab08-shine motion-reduce:hover:before:animate-none motion-reduce:transition-none">Upgrade Now</button>
      <button type="button" class="relative overflow-hidden min-h-11 px-9 text-[0.95rem] font-bold tracking-[0.04em] text-white bg-[linear-gradient(135deg,#4c1d95,#7c3aed,#a78bfa)] rounded-[10px] cursor-pointer transition-[translate,filter] duration-150 hover:brightness-110 hover:-translate-y-0.5 active:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab08-violet before:content-[''] before:absolute before:-top-[10%] before:-left-[20%] before:w-[60%] before:h-[120%] before:bg-[linear-gradient(105deg,transparent_30%,oklch(1_0_0/0.55)_50%,transparent_70%)] before:-skew-x-[15deg] before:-translate-x-full before:pointer-events-none hover:before:animate-tab08-shine focus-visible:before:animate-tab08-shine motion-reduce:hover:before:animate-none motion-reduce:transition-none">Get Premium</button>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tab08-bg: #f1f5f9;
  --color-tab08-bg: oklch(0.97 0.006 250);
  --color-tab08-mut: #64748b;
  --color-tab08-mut: oklch(0.55 0.03 255);
  --color-tab08-slate: #1e293b;
  --color-tab08-slate: oklch(0.28 0.03 258);
  --color-tab08-ink: #e2e8f0;
  --color-tab08-ink: oklch(0.92 0.01 250);
  --color-tab08-gold: #b45309;
  --color-tab08-gold: oklch(0.53 0.15 62);
  --color-tab08-violet: #4c1d95;
  --color-tab08-violet: oklch(0.36 0.2 296);
  --font-tab08-sans: 'Space Grotesk', system-ui, sans-serif;
  --animate-tab08-shine: tab08-shine 0.55s ease-in-out forwards;
}

@keyframes tab08-shine {
  0% {
    translate: -100% 0;
  }

  100% {
    translate: 400% 0;
  }
}

.tab-08 {
  width: 100%;
  min-height: 100svh;
}

.tab-08 ::selection {
  background: var(--color-tab08-slate);
  color: #fff;
}
```

How this works

The streak is a gradient, not an image. Three stops — transparent, 55% white, transparent — give a soft-edged band. overflow-hidden clips it as it enters and leaves, so the button appears to have a gloss surface rather than a moving child.

Skew is a utility; translate is the keyframe. Tailwind's -skew-x-* composes with the keyframe's translateX because v4 writes transforms through individual custom properties — something the CSS original had to do by repeating skewX(-15deg) in both keyframe steps.

Re-trigger on re-entry is free. Leaving the button removes :hover, which unbinds the animation; the next entry starts it from frame zero. No JS, no class toggling.

Make it yours

  • Wider flash: widen the gradient's middle band from 30%…70% to 20%…80%.
  • Steeper cut: -skew-x-[15deg] → -skew-x-[30deg].
  • Gold gloss: replace the white stop with oklch(0.9_0.13_90/0.55).

Gotchas — read before shipping

  • Fast pointer oscillation at the button edge can restart the sweep mid-pass. It is inherent to hover-triggered animations; a JS class toggle is the only fix and is rarely worth it.
  • On iOS, :hover sticks after a tap, so the streak plays once and stays parked — acceptable, but do not build meaning into the sweep.
  • overflow-hidden clips shadow-* too. The lift here uses translate only, for exactly that reason.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Gradients and transform animations are universally supported; the floor is Tailwind v4's generated sheet.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…