Pure TailwindMIT licensed

Tailwind Background Slide Hover Button (Four Directions)

Four directional fills that sweep across the button face — left, right, top, bottom. The port collapses eight CSS rules (four resting transforms, four hover transforms) into four class lists, each stating its own direction: before:-translate-x-full hover:before:translate-x-0.

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-02 w-full min-h-svh grid place-items-center bg-tab02-bg font-tab02-sans px-6 py-10">
  <div class="flex flex-col items-center gap-8">
    <p class="text-[0.8rem] font-semibold tracking-[0.12em] uppercase text-tab02-fill/70 m-0">Background Slide Directions</p>
    <div class="grid grid-cols-2 gap-4">
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:-translate-x-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-x-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-x-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Left</span></button>
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:translate-x-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-x-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-x-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Right</span></button>
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:-translate-y-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-y-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Top</span></button>
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:translate-y-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-y-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Bottom</span></button>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tab02-bg: #f0eeff;
  --color-tab02-bg: oklch(0.95 0.02 282);
  --color-tab02-fill: #6c63ff;
  --color-tab02-fill: oklch(0.56 0.21 282);
  --font-tab02-sans: 'Space Grotesk', system-ui, sans-serif;
}

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

.tab-02 ::selection {
  background: var(--color-tab02-fill);
  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-tab02-bg: #f0eeff;
  --color-tab02-bg: oklch(0.95 0.02 282);
  --color-tab02-fill: #6c63ff;
  --color-tab02-fill: oklch(0.56 0.21 282);
  --font-tab02-sans: 'Space Grotesk', system-ui, sans-serif;
}

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

.tab-02 ::selection {
  background: var(--color-tab02-fill);
  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.

  • Eight CSS rules become four class lists. The repetition moved from the stylesheet into the markup, which is the trade every directional-variant port makes — and here it is worth it, because direction is now stated where the button is.
  • before:content-[''] is mandatory in Tailwind: a pseudo-element with no content does not render, and the utility set does not imply it.
  • UI change from the CSS original: every hover state gained a focus-visible twin and the buttons gained 44px minimum height.
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 Background Slide Hover Button (Four Directions)
Source: https://codefronts.com/motion/tailwind-css-animated-buttons/tailwind-background-slide-hover-button/

Four directional fills that sweep across the button face &mdash; left, right, top, bottom. The port collapses eight CSS rules (four resting transforms, four hover transforms) into four class lists, each stating its own direction: before:-translate-x-full hover:before:translate-x-0.
## HTML
```html
<section class="tab-02 w-full min-h-svh grid place-items-center bg-tab02-bg font-tab02-sans px-6 py-10">
  <div class="flex flex-col items-center gap-8">
    <p class="text-[0.8rem] font-semibold tracking-[0.12em] uppercase text-tab02-fill/70 m-0">Background Slide Directions</p>
    <div class="grid grid-cols-2 gap-4">
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:-translate-x-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-x-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-x-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Left</span></button>
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:translate-x-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-x-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-x-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Right</span></button>
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:-translate-y-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-y-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Top</span></button>
      <button type="button" class="relative overflow-hidden min-h-11 px-8 text-[0.95rem] font-bold tracking-[0.03em] text-tab02-fill bg-transparent border-2 border-tab02-fill rounded-lg cursor-pointer transition-colors duration-[350ms] before:content-[''] before:absolute before:inset-0 before:bg-tab02-fill before:translate-y-full before:transition-transform before:duration-[350ms] before:ease-[cubic-bezier(0.4,0,0.2,1)] hover:text-white hover:before:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tab02-fill focus-visible:text-white focus-visible:before:translate-y-0 active:scale-[0.97] motion-reduce:before:transition-none motion-reduce:transition-none"><span class="relative z-10">Slide Bottom</span></button>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tab02-bg: #f0eeff;
  --color-tab02-bg: oklch(0.95 0.02 282);
  --color-tab02-fill: #6c63ff;
  --color-tab02-fill: oklch(0.56 0.21 282);
  --font-tab02-sans: 'Space Grotesk', system-ui, sans-serif;
}

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

.tab-02 ::selection {
  background: var(--color-tab02-fill);
  color: #fff;
}
```

How this works

The direction is now a word in the class list. The CSS version needed a modifier class per direction plus a paired hover rule — eight selectors to express four behaviours. Tailwind states the resting transform and the hover transform on the same element:

before:-translate-x-full hover:before:translate-x-0

so "slides in from the left" is legible without cross-referencing a stylesheet. Only transform animates, so the compositor does all the work.

The fill inherits the token. before:bg-tab02-fill and border-tab02-fill read one @theme colour, so the resting outline and the incoming fill can never drift apart.

Focus is a first-class state. Each button pairs every hover:before: with a focus-visible:before:, so a keyboard user sees the same sweep a mouse user does — a genuine upgrade over the hover-only original.

Make it yours

  • Gradient fill: swap before:bg-tab02-fill for before:bg-[linear-gradient(135deg,#6c63ff,#c471ed)].
  • Speed: before:duration-[350ms] → before:duration-200 for a snappier sweep.
  • Diagonal sweep: combine two axes — before:-translate-x-full before:-translate-y-full hover:before:translate-x-0 hover:before:translate-y-0.

Gotchas — read before shipping

  • overflow-hidden clips shadow-* as well as the fill. If you need both, move the shadow to a wrapper.
  • The label needs relative z-10. Without it the fill paints over the text and the button appears to go blank on hover.
  • Keep before:inset-0 rather than a percentage width — percentage sizing on an absolutely-positioned pseudo-element inside flex or grid can resolve against the wrong box.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Pseudo-element transforms are universally supported; the floor is Tailwind v4's generated sheet.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…