| Author: | FBalint |
|---|---|
| Views Total: | 60 views |
| Official Page: | Go to website |
| Last Update: | July 10, 2025 |
| License: | MIT |
Preview:

Description:
The 3D Pressable Button is a pure CSS component that creates realistic physical button interactions using layered SVG and CSS3 transforms.
It responds to user interactions with three distinct states and can be customized through CSS custom properties without requiring any JavaScript.
See it in action:
How to use it:
1. The button requires three SVG assets (base, button, and cover) plus HTML structure:
<div class="frame">
<img class="base" src="./assets/base.svg" alt="image">
<img class="button" src="./assets/button.svg" alt="image">
<svg class="recolor-overlay" width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M165.675 45.467C175.026 44.5675 185.116 47.156 197.282 51.1232C232.426 62.5832 267.932 74.4187 307.642 86.6369C312.212 88.0431 315.403 89.8794 317.44 92.1486C318.511 93.341 319.241 94.6327 319.691 96.0011C319.738 96.0238 319.777 96.0473 319.808 96.0734C323.933 99.6423 327.485 108.542 328.746 112.546C333.559 127.417 343.667 158.667 345.593 164.707C347.829 171.722 351.843 177.846 347.437 185.285C347.318 185.578 347.187 185.873 347.042 186.169L346.987 186.005C346.768 186.338 346.534 186.675 346.28 187.013C340.092 195.249 293.679 246.724 273.395 270.745C253.112 294.767 245.626 307.362 209.871 297.41C174.117 287.459 88.3902 254.694 68.1503 244.665C49.7396 235.543 50.9605 229.908 53.7108 219.613C55.9113 211.377 69.9838 160.36 76.745 135.881C76.8387 135.864 76.9324 135.846 77.0263 135.828C77.2577 135.071 77.5382 134.315 77.8554 133.559C78.637 130.76 80.1703 127.902 81.913 124.901C87.4843 115.306 101.154 100.903 107.267 94.9152L112.901 88.7316C117.228 83.8274 124.233 75.8678 138.572 60.5568C147.707 50.8031 156.252 46.3734 165.675 45.467Z" fill="currentColor"/>
</svg>
<img class="cover" src="./assets/cover.svg" alt="image">
<p class="text">Custom Button text</p>
</div>2. Add the following CSS to your stylesheet. The main configuration happens in the .frame class via custom properties.
.frame {
position: relative;
/* Button dimensions */
width: 400px;
height: 400px;
/* Movement distances */
--hover-travel: 3px;
--press-travel: 40px;
/* Color customization */
--color: black;
--brightness: 1;
--blend-mode: color;
/* Transition settings */
--transition-duration: 0.4s;
--transition-easing: linear(0, 0.008 1.1%, 0.031 2.2%, 0.129 4.8%, 0.257 7.2%, 0.671 14.2%, 0.789 16.5%, 0.881 18.6%, 0.957 20.7%, 1.019 22.9%, 1.063 25.1%, 1.094 27.4%, 1.114 30.7%, 1.112 34.5%, 1.018 49.9%, 0.99 59.1%, 1);
}
.frame, .recolor-overlay, .button, .text {
user-select: none;
}
.base {
width: 100%; height: 100%;
}
.recolor-overlay {
position: absolute;
width: 100%; height: 100%;
color: var(--color);
top: 0;
left: 0;
mix-blend-mode: var(--blend-mode);
transition-property: all;
transition-duration: var(--transition-duration);
transition-timing-function: var(--transition-easing);
}
.button {
position: absolute;
width: 100%; height: 100%;
top: 0;
left: 0;
filter: brightness(var(--brightness));
transition-property: all;
transition-duration: var(--transition-duration);
transition-timing-function: var(--transition-easing);
}
.cover {
position: absolute;
top: 0;
left: 0;
width: 100%; height: 100%;
}
.frame:hover .button, .frame:hover .text, .frame:hover .recolor-overlay {
margin-top: var(--hover-travel);
}
.frame:active .button, .frame:active .text, .frame:active .recolor-overlay {
margin-top: var(--press-travel);
}
.text {
font-family: sans-serif;
font-size: 2rem;
color: white;
white-space: nowrap;
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
text-align: center;
align-content: center;
translate: -50% -50%;
transform: rotateY(0deg) rotateX(52.3deg) rotateZ(29deg) translateY(-28%) translateX(-16%);
margin: 0px;
padding: 0px;
transition-property: all;
transition-timing-function: var(--transition-easing);
transition-duration: var(--transition-duration);
}






