7 Creative Hover Effects Using CSS Box-Shadow

Category: Animation , CSS & CSS3 | February 19, 2026
Authordavidbiek
Last UpdateFebruary 19, 2026
LicenseMIT
Views0 views
7 Creative Hover Effects Using CSS Box-Shadow

A pure CSS snippet that provides seven smoothly animated button hover effects using only the CSS box-shadow property and CSS custom properties.

Features:

  • 7 effects: fill, pulse, close, raise, up, slide, and offset.
  • CSS custom properties: Colors are controlled via --color and --hover CSS variables.
  • Inset shadow technique: Uses the inset keyword on box-shadow to fake a fill animation from any direction.
  • Smooth stacked shadows: Where multiple shadows are needed, the snippet maintains the same shadow count on both the default and :hover states.
  • Focus state support: Every :hover rule is paired with :focus.

See It In Action:

Use Cases:

  • Call-to-Action Buttons: You can use the “Fill” or “Pulse” effects to draw attention to primary actions like “Sign Up” or “Buy Now.”
  • Navigation Menus: The “Underline” or “Slide” effects work well for distinct hover states in navbar links.
  • Form Submission: The “Raise” effect provides tactile feedback when a user interacts with submit buttons.
  • Interactive Cards: You can apply the “Offset” shadow style to card components to give them depth on hover.

How To Use It:

1. Copy the full CSS snippet below. Each class defines its own --color and --hover CSS variables, then overrides box-shadow on :hover and :focus.

/* --- FILL: inset shadow expands from all edges simultaneously --- */
.fill {
  --color: #a972cb;
  --hover: #cb72aa;
}
.fill:hover,
.fill:focus {
  /* A single inset shadow with 2em spread covers the full button face */
  box-shadow: inset 0 0 0 2em var(--hover);
}
/* --- PULSE: radiating ring animation using @keyframes --- */
.pulse {
  --color: #ef6eae;
  --hover: #ef8f6e;
}
.pulse:hover,
.pulse:focus {
  /* End state is transparent so the ring fades out after expanding */
  animation: pulse 1s;
  box-shadow: 0 0 0 2em transparent;
}
@keyframes pulse {
  0% {
    /* Ring starts at 0 radius in the hover color, then expands to 2em transparent above */
    box-shadow: 0 0 0 0 var(--hover);
  }
}
/* --- CLOSE: two inset shadows fill from left and right simultaneously --- */
.close {
  --color: #ff7f82;
  --hover: #ffdc7f;
}
.close:hover,
.close:focus {
  /* Negative left offset (-3.5em) fills from the right; positive fills from the left */
  box-shadow:
    inset -3.5em 0 0 0 var(--hover),
    inset  3.5em 0 0 0 var(--hover);
}
/* --- RAISE: shadow appears below and the button lifts via translateY --- */
.raise {
  --color: #ffa260;
  --hover: #e5ff60;
}
.raise:hover,
.raise:focus {
  /* Negative spread (-0.4em) gives the shadow a soft underside edge */
  box-shadow: 0 0.5em 0.5em -0.4em var(--hover);
  transform: translateY(-0.25em); /* Lifts the button 0.25em upward */
}
/* --- UP: inset shadow fills from the bottom edge upward --- */
.up {
  --color: #e4cb58;
  --hover: #94e458;
}
.up:hover,
.up:focus {
  /* Large negative top value (-3.25em) anchors the shadow at the bottom */
  box-shadow: inset 0 -3.25em 0 0 var(--hover);
}
/* --- SLIDE: inset shadow sweeps in from the left --- */
.slide {
  --color: #8fc866;
  --hover: #66c887;
}
.slide:hover,
.slide:focus {
  /* 6.5em left offset pushes the shadow origin to the left edge */
  box-shadow: inset 6.5em 0 0 0 var(--hover);
}
/* --- OFFSET: resting state has a visible outer + inner corner shadow;
       hover collapses the outer shadow and floods the inner one --- */
.offset {
  --color: #19bc8b;
  --hover: #1973bc;
}
.offset {
  /* Two shadows create a "double border" corner effect at rest */
  box-shadow:
    0.3em 0.3em 0 0 var(--color),
    inset 0.3em 0.3em 0 0 var(--color);
}
.offset:hover,
.offset:focus {
  /* First shadow collapses to 0; second floods the button interior */
  box-shadow:
    0 0 0 0 var(--hover),
    inset 6em 3.5em 0 0 var(--hover);
}

2. Apply these hover effects to your DOM elements like buttons.

<button class="fill">Fill In</button>
<button class="pulse">Pulse</button>
<button class="close">Close</button>
<button class="raise">Raise</button>
<button class="up">Fill Up</button>
<button class="slide">Slide</button>
<button class="offset">Offset</button>

Alternatives:

  • Hover.css: A comprehensive collection of CSS hover effects covering borders, shadows, text, and background transitions. It’s a broader library compared to this focused box-shadow approach.
  • CSShake: Specializes in shake and vibration animations triggered on hover.
  • Hover Effects: Discover more hover effects at CSSScript.com.

FAQs:

Q: Why are my hover transitions choppy on the offset button?
A: Your resting box-shadow and hover box-shadow have a different number of shadow layers. CSS interpolates between shadows position-by-position. If the count mismatches, the browser can’t calculate intermediate values and jumps directly between states.

Q: Can I apply multiple effects to the same button?
A: Technically yes, but the box-shadow property is a single list. Two effect classes will overwrite each other’s box-shadow on hover, and only the last rule in the cascade wins.

Q: Do these effects work on elements other than <button>?
A: Yes. The classes work on any block or inline-block element. For anchor tags, add display: inline-block so padding and shadow geometry are computed correctly.

Q: How do I adjust the fill speed?
A: Change the transition duration on the base button rule. The current value is 0.25s. Increasing it to 0.4s or 0.5s gives a more deliberate, cinematic feel.

Q: Is there a risk of these effects conflicting with a CSS reset or framework like Tailwind?
A: Yes, if your framework resets box-shadow to none via a utility class or base layer, the transitions will not animate — they’ll snap. Check that no utility class on the button overrides box-shadow at a higher specificity. In Tailwind, this means avoiding shadow-none on the same element, or adding the effect classes after the framework’s stylesheet in your <head>.

You Might Be Interested In:


Leave a Reply