20 CSS Animated Buttons05 / 20

Pure CSSMIT licensed

CSS 3D Press Effect Button

A tactile 3D button that physically sinks into its own raised platform on click, simulating a keycap-style press using CSS transforms and layered box-shadows.

Published

Live Demo
Try it

The code

<div class="ab-05">
  <p class="ab-05__label">Click or tap the buttons</p>
  <div class="ab-05__row">
    <button class="ab-05__btn ab-05__btn--indigo">Purchase Now</button>
    <button class="ab-05__btn ab-05__btn--emerald">Download App</button>
    <button class="ab-05__btn ab-05__btn--rose">Delete File</button>
  </div>
</div>
.ab-05,
.ab-05 *,
.ab-05 *::before,
.ab-05 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.ab-05 ::selection {
  background: #4338ca;
  color: #fff;
}

.ab-05 {
  font-family: system-ui,sans-serif;
  background: #f8fafc;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
  padding: 2rem;
}

.ab-05__label {
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #64748b;
}

.ab-05__row {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  justify-content: center;
}

.ab-05__btn {
  --face: #6366f1;
  --depth: #3730a3;
  position: relative;
  padding: .85rem 2.2rem;
  font-size: 1rem;
  font-weight: 800;
  color: #fff;
  background: var(--face);
  border: none;
  border-radius: 10px;
  cursor: pointer;
  outline: none;
  letter-spacing: .03em;
  box-shadow: 0 6px 0 var(--depth),0 8px 12px rgba(0,0,0,.18);
  transition: transform .08s,box-shadow .08s;
  will-change: transform;
  user-select: none;
}

.ab-05__btn--indigo {
  --face: #6366f1;
  --depth: #3730a3;
}

.ab-05__btn--emerald {
  --face: #10b981;
  --depth: #065f46;
}

.ab-05__btn--rose {
  --face: #f43f5e;
  --depth: #9f1239;
}

.ab-05__btn:hover {
  filter: brightness(1.05);
}

.ab-05__btn:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 var(--depth),0 4px 6px rgba(0,0,0,.12);
}

@media (prefers-reduced-motion: reduce) {
  .ab-05__btn {
    transition: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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 3D Press Effect Button
Source: https://codefronts.com/motion/css-animated-buttons/css-3d-press-effect-button/

A tactile 3D button that physically sinks into its own raised platform on click, simulating a keycap-style press using CSS transforms and layered box-shadows.
## HTML
```html
<div class="ab-05">
  <p class="ab-05__label">Click or tap the buttons</p>
  <div class="ab-05__row">
    <button class="ab-05__btn ab-05__btn--indigo">Purchase Now</button>
    <button class="ab-05__btn ab-05__btn--emerald">Download App</button>
    <button class="ab-05__btn ab-05__btn--rose">Delete File</button>
  </div>
</div>
```
## CSS
```css
.ab-05,
.ab-05 *,
.ab-05 *::before,
.ab-05 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.ab-05 ::selection {
  background: #4338ca;
  color: #fff;
}

.ab-05 {
  font-family: system-ui,sans-serif;
  background: #f8fafc;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
  padding: 2rem;
}

.ab-05__label {
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #64748b;
}

.ab-05__row {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  justify-content: center;
}

.ab-05__btn {
  --face: #6366f1;
  --depth: #3730a3;
  position: relative;
  padding: .85rem 2.2rem;
  font-size: 1rem;
  font-weight: 800;
  color: #fff;
  background: var(--face);
  border: none;
  border-radius: 10px;
  cursor: pointer;
  outline: none;
  letter-spacing: .03em;
  box-shadow: 0 6px 0 var(--depth),0 8px 12px rgba(0,0,0,.18);
  transition: transform .08s,box-shadow .08s;
  will-change: transform;
  user-select: none;
}

.ab-05__btn--indigo {
  --face: #6366f1;
  --depth: #3730a3;
}

.ab-05__btn--emerald {
  --face: #10b981;
  --depth: #065f46;
}

.ab-05__btn--rose {
  --face: #f43f5e;
  --depth: #9f1239;
}

.ab-05__btn:hover {
  filter: brightness(1.05);
}

.ab-05__btn:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 var(--depth),0 4px 6px rgba(0,0,0,.12);
}

@media (prefers-reduced-motion: reduce) {
  .ab-05__btn {
    transition: none;
  }
}
```

How this works

The raised look is created by a large bottom-offset box-shadow that acts as a physical "depth" layer below the button face — e.g. 0 6px 0 #4338ca gives 6px of solid underhang. On :active, a transform: translateY(4px) moves the button face downward to visually close most of that gap, while the box-shadow shrinks to 0 2px 0 … so the remaining depth appears compressed. This two-property change is all that's needed to sell the physical press illusion.

A subtle transition: transform .08s, box-shadow .08s on very short duration mimics the instantaneous spring of a real mechanical key. On release, the button springs back to its elevated position. will-change: transform keeps the active state transition on the GPU compositor. The label shifts up 1px on active via the same transform to add realism to the sinking feel.

Make it yours

  • Increase depth by raising the first box-shadow y-offset from 6px to 10px and matching the :active translateY to 8px.
  • Change the button colour by updating --face and setting --depth to a darker shade of the same hue (roughly 20% darker works well).
  • Round the button to a circle for icon-only press buttons by setting border-radius: 50% and equalising width and height.
  • Add a subtle inner bevel by adding an inset 0 1px 0 rgba(255,255,255,.25) shadow layer to the non-active state for a highlight on the top edge.
  • Pair with a click sound using the Web Audio API in JS — this CSS-only demo degrades to a purely visual effect without the audio layer.

Gotchas — read before shipping

  • If the button is inside a transform-ed container (e.g. a card with rotateY), the translateY on :active compounds with the parent transform — test in context.
  • Very fast repeated clicks can cause the transition to stutter — add user-select: none to prevent text selection on rapid tapping which interrupts the active state.
  • On touch devices the :active state is triggered by touchstart and released on touchend — this mirrors the keyboard press naturally without extra JS.

Browser support

ChromeSafariFirefoxEdge
36+9+16+36+

Uses only CSS transforms and box-shadows; universally supported.

Techniques used in this demo

Search CodeFronts

Loading…