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.
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
:activestates — they close the feedback loop and make clicks feel physical - Use
easeorease-outcurves —linearfeels mechanical,ease-infeels 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.