10 Creative CSS Hover Effects for Buttons You Can Copy

10 pure CSS button hover effects you can copy and use today — border animations, 3D push, gradient shifts, glow effects, and more. Production-ready code included.

·6 min read·Animation
10 Creative CSS Hover Effects for Buttons You Can Copy

A well-crafted hover effect makes a button feel intentional. A flat color swap on hover says "I used the default." These 10 CSS hover effects go beyond the basics — each one is pure CSS, production-ready, and easy to customize.

1. The 3D Push

A tactile press effect using translateY and shadow changes:

.btn-push {
  padding: 12px 28px;
  background: #6366f1;
  color: white;
  border: none;
  border-radius: 8px;
  box-shadow: 0 4px 0 #4338ca;
  transition: all 0.12s ease;
  cursor: pointer;
}

.btn-push:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 0 #4338ca;
}

.btn-push:active {
  transform: translateY(2px);
  box-shadow: 0 2px 0 #4338ca;
}

The shadow acts as a physical surface beneath the button. On hover it lifts, on click it pushes down. Simple physics, immediate impact.

2. Gradient Shift

The background gradient rotates on hover:

.btn-gradient {
  padding: 12px 28px;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  background-size: 200% 200%;
  background-position: 0% 50%;
  color: white;
  border: none;
  border-radius: 8px;
  transition: background-position 0.4s ease;
  cursor: pointer;
}

.btn-gradient:hover {
  background-position: 100% 50%;
}

3. Border Draw

An animated border that draws itself around the button using pseudo-elements:

.btn-border-draw {
  position: relative;
  padding: 12px 28px;
  background: transparent;
  color: #e2e8f0;
  border: none;
  cursor: pointer;
}

.btn-border-draw::before,
.btn-border-draw::after {
  content: "";
  position: absolute;
  width: 0;
  height: 0;
  border: 2px solid transparent;
  box-sizing: border-box;
  transition: all 0.35s ease;
}

.btn-border-draw::before {
  top: 0;
  left: 0;
}

.btn-border-draw::after {
  bottom: 0;
  right: 0;
}

.btn-border-draw:hover::before {
  width: 100%;
  height: 100%;
  border-top-color: #6366f1;
  border-right-color: #6366f1;
}

.btn-border-draw:hover::after {
  width: 100%;
  height: 100%;
  border-bottom-color: #6366f1;
  border-left-color: #6366f1;
}

Two pseudo-elements each draw two sides of the border, meeting at opposite corners.

4. Underline Slide

A bottom border that slides in from the left:

.btn-underline {
  position: relative;
  padding: 12px 28px;
  background: transparent;
  color: #e2e8f0;
  border: none;
  cursor: pointer;
}

.btn-underline::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0;
  height: 2px;
  background: #6366f1;
  transition: width 0.3s ease;
}

.btn-underline:hover::after {
  width: 100%;
}

Clean and minimal. Works great for navigation links and text-style buttons.

5. Background Fill

A colored background that slides in from one side:

.btn-fill {
  position: relative;
  padding: 12px 28px;
  background: transparent;
  color: #6366f1;
  border: 2px solid #6366f1;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  z-index: 1;
  transition: color 0.3s ease;
}

.btn-fill::before {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: #6366f1;
  transition: left 0.3s ease;
  z-index: -1;
}

.btn-fill:hover {
  color: white;
}

.btn-fill:hover::before {
  left: 0;
}

6. Glow Pulse

A soft glowing shadow that pulses on hover:

.btn-glow {
  padding: 12px 28px;
  background: #6366f1;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: box-shadow 0.3s ease;
}

.btn-glow:hover {
  box-shadow:
    0 0 15px rgba(99, 102, 241, 0.4),
    0 0 30px rgba(99, 102, 241, 0.2),
    0 0 45px rgba(99, 102, 241, 0.1);
}

Multiple shadow layers at increasing blur radii create a natural glow falloff.

7. Scale + Rotate

Subtle scale with a slight rotation creates a playful interaction:

.btn-scale-rotate {
  padding: 12px 28px;
  background: #6366f1;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.25s ease;
}

.btn-scale-rotate:hover {
  transform: scale(1.05) rotate(-1deg);
}

.btn-scale-rotate:active {
  transform: scale(0.97) rotate(0deg);
}

The slight rotation breaks rigidity and makes the button feel more organic. Keep the rotation subtle (1-2 degrees) — more than that looks sloppy.

8. Shine Sweep

A light sweep across the button surface:

.btn-shine {
  position: relative;
  padding: 12px 28px;
  background: #6366f1;
  color: white;
  border: none;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
}

.btn-shine::after {
  content: "";
  position: absolute;
  top: 0;
  left: -75%;
  width: 50%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.2),
    transparent
  );
  transform: skewX(-20deg);
  transition: left 0.5s ease;
}

.btn-shine:hover::after {
  left: 125%;
}

The skewed pseudo-element creates a diagonal light band that sweeps across the button.

9. Shadow Lift

The button lifts off the surface with an expanding shadow:

.btn-lift {
  padding: 12px 28px;
  background: #6366f1;
  color: white;
  border: none;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  cursor: pointer;
  transition: all 0.25s ease;
}

.btn-lift:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 25px rgba(99, 102, 241, 0.3);
}

.btn-lift:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

The shadow color shifts from neutral gray to the button's brand color on hover, reinforcing the glow effect.

10. Text Swap

The text slides out and a new label slides in (e.g., "Learn More" → "Let's Go"):

.btn-swap {
  position: relative;
  padding: 12px 28px;
  background: #6366f1;
  color: white;
  border: none;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
}

.btn-swap span {
  display: block;
  transition: transform 0.3s ease;
}

.btn-swap .default {
  transform: translateY(0);
}

.btn-swap .hover-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateY(100%);
  transition: transform 0.3s ease;
}

.btn-swap:hover .default {
  transform: translateY(-100%);
}

.btn-swap:hover .hover-text {
  transform: translateY(0);
}

This requires two text elements in the HTML — the default label and the hover label. The effect works best when the swap text is slightly different (shorter or more action-oriented).

Usage Tips

  • Keep durations between 0.15s and 0.35s — faster feels responsive, slower feels sluggish
  • Always include :active states — they close the feedback loop and make clicks feel physical
  • Use ease or ease-out curveslinear feels mechanical, ease-in feels delayed
  • Test on touch devices — hover effects don't work on mobile, so ensure the button still looks good without them
  • Don't combine too many effects — one well-executed effect beats three mediocre ones stacked together

Beyond Hover: Additional Techniques

clip-path enables hold-effect buttons that reveal different icons contextually. Animate the clip-path value to create reveal and conceal transitions on press-and-hold — for example, a send icon that morphs into a cancel icon while the user holds the button down.

Consider replacing borders with layered box-shadows for more depth: box-shadow: 0px 0px 0px 1px rgba(0,0,0,0.06), 0px 1px 2px -1px rgba(0,0,0,0.06). The first layer acts as a 1px border, and the second adds a subtle lift. Shadows adapt better across different backgrounds than hard borders, which can look harsh on dark surfaces.

One thing that trips people up: optical alignment. Play icons inside circular buttons need the padding reduced on the icon's right side. Geometric center looks off because triangles carry uneven visual weight — the point "pulls" the eye right, so you nudge the icon slightly left to compensate. The same principle applies to any asymmetric icon in a symmetrical container.

More Articles