Tech

CSS Tips

Button Hover Animation with Sliding Background

Combine pseudo-elements and transform to create an impressive button hover effect.

Coding css animation

Introduction

Button hover effects are an important element for visually communicating user interaction.

This article introduces how to create an animation where the background color appears from left to right on hover and disappears to the right when unhovered, using only CSS.

Completed Demo

Hover over the button. The background slides in from the left, and slides out to the right when you move away.

Preview
HTML
<button class="demo-hover-btn">Hover me!</button>
CSS
.demo-hover-btn {
  padding: 1rem 2rem;
  font-size: 1rem;
  font-weight: 600;
  border: 2px solid #667eea;
  background: transparent;
  color: #667eea;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  transition: color 0.3s ease;
  isolation: isolate;
}

.demo-hover-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s ease;
  z-index: -1;
}

.demo-hover-btn:hover {
  color: #fff;
}

.demo-hover-btn:hover::before {
  transform: scaleX(1);
  transform-origin: left;
}

How It Works

This animation is achieved by combining the ::before pseudo-element and transform: scaleX().

Here are the three key points:

1. **Create a background layer with pseudo-element**
Use ::before to create a background color layer that covers the entire button.

2. **Hide initially with scaleX(0)**
Setting the horizontal scale to 0 makes it invisible at first.

3. **Control direction with transform-origin**
By setting left (expands from left) on hover and right (shrinks to right) when not hovered, you create a unidirectional flowing animation.

HTML Code

<button class="hover-btn">Hover me!</button>

CSS Code

.hover-btn {
  padding: 1rem 2rem;
  font-size: 1rem;
  font-weight: 600;
  border: 2px solid #667eea;
  background: transparent;
  color: #667eea;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  transition: color 0.3s ease;
  isolation: isolate; /* Create new stacking context */
}

.hover-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s ease;
  z-index: -1;
}

.hover-btn:hover {
  color: #fff;
}

.hover-btn:hover::before {
  transform: scaleX(1);
  transform-origin: left;
}

Role of Each Property

position: relative

Sets the button as a reference point so the pseudo-element with position: absolute is positioned correctly within the button.

overflow: hidden

Clips the pseudo-element so it doesn't overflow the button's boundaries.

inset: 0

Shorthand for setting top, right, bottom, and left all to 0. The pseudo-element covers the entire button.

transform: scaleX(0)

Scales the element's width to 0 (invisible). scaleX(1) returns it to original size.

transform-origin

Specifies the transformation's origin point. 'right' scales from the right edge, 'left' from the left edge.

z-index: -1

Places the pseudo-element behind the button text so the text remains visible.

isolation: isolate

Creates a new stacking context. This ensures the z-index: -1 pseudo-element stays within the button.

The Key: Switching transform-origin

The most important aspect of this animation is switching transform-origin between hover and non-hover states.

**Non-hover state**: transform-origin: right;
→ With scaleX(0) from the right edge, it shrinks and disappears to the right

**Hover state**: transform-origin: left;
→ With scaleX(1) from the left edge, it expands and appears from the left

This switch creates a unidirectional animation: appearing from left on hover, disappearing to right on unhover.

Color Variations

By simply changing the background color, you can create buttons with various moods.

Preview
HTML
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
  <button class="demo-hover-btn demo-hover-btn--green">Green</button>
  <button class="demo-hover-btn demo-hover-btn--orange">Orange</button>
  <button class="demo-hover-btn demo-hover-btn--pink">Pink</button>
</div>
CSS
.demo-hover-btn {
  padding: 1rem 2rem;
  font-size: 1rem;
  font-weight: 600;
  border: 2px solid #667eea;
  background: transparent;
  color: #667eea;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  transition: color 0.3s ease;
  isolation: isolate;
}

.demo-hover-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s ease;
  z-index: -1;
}

.demo-hover-btn:hover {
  color: #fff;
}

.demo-hover-btn:hover::before {
  transform: scaleX(1);
  transform-origin: left;
}

.demo-hover-btn--green {
  border-color: #00b894;
  color: #00b894;
}

.demo-hover-btn--green::before {
  background: linear-gradient(135deg, #00b894 0%, #00a885 100%);
}

.demo-hover-btn--orange {
  border-color: #fdcb6e;
  color: #e17055;
}

.demo-hover-btn--orange::before {
  background: linear-gradient(135deg, #fdcb6e 0%, #e17055 100%);
}

.demo-hover-btn--pink {
  border-color: #fd79a8;
  color: #fd79a8;
}

.demo-hover-btn--pink::before {
  background: linear-gradient(135deg, #fd79a8 0%, #e84393 100%);
}

Application Examples

This technique can be applied to various elements beyond buttons.

**Link Hover Effects**
You can animate text link underlines using this method.

**Card Hover**
Apply this effect to entire cards for background color changes on hover.

**Navigation Menus**
Create sliding background effects for menu items on hover.

Summary

By combining pseudo-elements, transform: scaleX(), and switching transform-origin, you can create impressive button hover effects.

Since it's achieved with CSS only without JavaScript, it's also excellent for performance. Customize colors and animation speeds to incorporate this into your projects.