20 CSS Animated Buttons05 / 20
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
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><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;
}
}.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;
}
}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;
}
}
```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-shadowy-offset from6pxto10pxand matching the:activetranslateYto8px. - Change the button colour by updating
--faceand setting--depthto 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 equalisingwidthandheight. - 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 withrotateY), thetranslateYon:activecompounds with the parent transform — test in context. - Very fast repeated clicks can cause the
transitionto stutter — adduser-select: noneto prevent text selection on rapid tapping which interrupts the active state. - On touch devices the
:activestate is triggered bytouchstartand released ontouchend— this mirrors the keyboard press naturally without extra JS.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 36+ | 9+ | 16+ | 36+ |
Uses only CSS transforms and box-shadows; universally supported.