20 CSS Animated Buttons 02 / 20

CSS Background Slide Hover Button

Four directional background-slide hover buttons — left, right, top, and bottom — where a solid fill sweeps across the button face on hover using CSS pseudo-element transforms.

Pure CSS MIT licensed
Live Demo Open in tab
Open in playground

The code

<div class="ab-02">
  <p class="ab-02__title">Background Slide Directions</p>
  <div class="ab-02__grid">
    <button class="ab-02__btn ab-02__btn--left"><span>Slide Left</span></button>
    <button class="ab-02__btn ab-02__btn--right"><span>Slide Right</span></button>
    <button class="ab-02__btn ab-02__btn--top"><span>Slide Top</span></button>
    <button class="ab-02__btn ab-02__btn--bottom"><span>Slide Bottom</span></button>
  </div>
</div>
.ab-02,.ab-02 *,.ab-02 *::before,.ab-02 *::after{box-sizing:border-box;margin:0;padding:0}
.ab-02 ::selection{background:#6c63ff;color:#fff}
.ab-02{
  --fill:#6c63ff;
  --text:#1a1a2e;
  --border:#6c63ff;
  font-family:system-ui,sans-serif;
  background:#f0eeff;
  min-height:100vh;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:2rem;
  padding:2rem;
}
.ab-02__title{
  font-size:.8rem;
  font-weight:600;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:#6c63ff;
  opacity:.7;
}
.ab-02__grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:1rem;
}
.ab-02__btn{
  position:relative;
  overflow:hidden;
  padding:.8rem 2rem;
  font-size:.95rem;
  font-weight:700;
  color:var(--fill);
  background:transparent;
  border:2px solid var(--border);
  border-radius:8px;
  cursor:pointer;
  outline:none;
  transition:color .35s;
  letter-spacing:.03em;
}
.ab-02__btn span{
  position:relative;
  z-index:1;
}
.ab-02__btn::before{
  content:'';
  position:absolute;
  inset:0;
  background:var(--fill);
  transition:transform .35s cubic-bezier(.4,0,.2,1);
  z-index:0;
}
.ab-02__btn:hover{color:#fff}
.ab-02__btn--left::before{transform:translateX(-100%)}
.ab-02__btn--left:hover::before{transform:translateX(0)}
.ab-02__btn--right::before{transform:translateX(100%)}
.ab-02__btn--right:hover::before{transform:translateX(0)}
.ab-02__btn--top::before{transform:translateY(-100%)}
.ab-02__btn--top:hover::before{transform:translateY(0)}
.ab-02__btn--bottom::before{transform:translateY(100%)}
.ab-02__btn--bottom:hover::before{transform:translateY(0)}
.ab-02__btn:active{transform:scale(.97)}
@media(prefers-reduced-motion:reduce){
  .ab-02__btn::before{transition:none}
  .ab-02__btn{transition:none}
}

How this works

Each button contains a ::before pseudo-element that covers the full button area and holds the hover fill colour. By default the pseudo-element is pushed out of view using transform: translateX(-100%) (left variant), translateX(100%) (right), translateY(-100%) (top), or translateY(100%) (bottom). On :hover the transform resets to translate(0) which slides the fill into place over a transition of 0.35 s with a smooth ease curve.

The button text sits in a position: relative; z-index: 1 span so it always renders above the sliding fill layer. overflow: hidden on the button itself clips the pseudo-element as it enters from its starting edge, making the slide feel contained and intentional. Only transform is animated, so the browser compositor handles all motion without repaints.

Customize

  • Change the slide direction by swapping the initial transform on ::before — use translateY(-100%) for a top-down sweep.
  • Adjust slide speed by editing the transition duration on .ab-02__btn::before (default .35s; try .2s for snappier feel).
  • Use a gradient fill instead of a solid by replacing the background on ::before with linear-gradient(135deg, #6c63ff, #c471ed).
  • Change text colour on hover by adding a transition: color .35s to the button and setting .ab-02__btn:hover { color: #fff }.
  • Stack two pseudo-elements (::before and ::after) with offset delays to create a two-tone layered slide effect.

Watch out for

  • The overflow: hidden on the button clips box-shadow — move the shadow to a wrapper element if you need both an outer glow and the slide effect.
  • If the button has border-radius, the pseudo-element corners are correctly clipped, but verify on Safari < 15 where overflow clipping with transforms occasionally mis-clips.
  • Avoid width: auto on ::before — always use 100% explicitly, as percentage widths in absolutely-positioned pseudo-elements can calculate incorrectly inside flex or grid containers.

Browser support

ChromeSafariFirefoxEdge
49+ 9.1+ 44+ 49+

Universally supported; relies only on CSS transforms and pseudo-elements.

Search CodeFronts

Loading…