20 CSS Animated Buttons02 / 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.
Published
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><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;
}
}.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;
}
}Here's a working CSS Animated Button 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: CSS Background Slide Hover Button
Source: https://codefronts.com/motion/css-animated-buttons/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.
## HTML
```html
<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>
```
## CSS
```css
.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;
}
}
```Here's a working CSS Animated Button 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: CSS Background Slide Hover Button
Source: https://codefronts.com/motion/css-animated-buttons/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.
## HTML
```html
<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>
```
## CSS
```css
.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.
Make it yours
- Change the slide direction by swapping the initial
transformon::before— usetranslateY(-100%)for a top-down sweep. - Adjust slide speed by editing the
transitionduration on.ab-02__btn::before(default.35s; try.2sfor snappier feel). - Use a gradient fill instead of a solid by replacing the
backgroundon::beforewithlinear-gradient(135deg, #6c63ff, #c471ed). - Change text colour on hover by adding a
transition: color .35sto the button and setting.ab-02__btn:hover { color: #fff }. - Stack two pseudo-elements (
::beforeand::after) with offset delays to create a two-tone layered slide effect.
Gotchas — read before shipping
- The
overflow: hiddenon the button clipsbox-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: autoon::before— always use100%explicitly, as percentage widths in absolutely-positioned pseudo-elements can calculate incorrectly inside flex or grid containers.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 49+ | 9.1+ | 44+ | 49+ |
Universally supported; relies only on CSS transforms and pseudo-elements.