├── .gitignore
├── README.md
├── assets
├── base.svg
├── button.svg
├── cover.svg
└── recolor-overlay.svg
├── index.html
└── styles.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # macOS system files
2 | .DS_Store
3 | **/.DS_Store
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 3D Pressable Button
2 |
3 |
4 | A realistic 3D button component built with HTML, CSS, and SVG that simulates the feel of pressing a physical button. The button features smooth animations, customizable colors, and responsive interactions.
5 |
6 |
7 | Created by [@BalintFerenczy](https://x.com/BalintFerenczy)
8 |
9 | Inspired by the amazing work at [Resend](https://resend.com/)
10 |
11 |
12 | ## Features
13 |
14 | - **Realistic 3D appearance** using layered SVG graphics
15 | - **Smooth animations** with custom easing functions
16 | - **Interactive states** - hover and press effects
17 | - **Customizable colors** through CSS variables
18 | - **Responsive design** that scales with container size
19 |
20 | ## Demo
21 |
22 | The button responds to user interactions with three distinct states:
23 | - **Normal**: The button in its resting position
24 | - **Hover**: Subtle downward movement when mouse hovers over
25 | - **Active**: Significant downward movement when pressed/clicked
26 |
27 | ## Usage
28 |
29 | ### Customization
30 |
31 | The button can be easily customized using CSS custom properties:
32 |
33 | ```css
34 | .frame {
35 | /* Button dimensions */
36 | width: 400px;
37 | height: 400px;
38 |
39 | /* Movement distances */
40 | --hover-travel: 3px;
41 | --press-travel: 40px;
42 |
43 | /* Color customization */
44 | --color: black;
45 | --brightness: 1;
46 | --blend-mode: color;
47 |
48 | /* Transition settings */
49 | --transition-duration: 0.4s;
50 | --transition-easing: ease-in-out;
51 | }
52 | ```
53 |
54 | #### Changing Button Text
55 |
56 | Simply modify the text content:
57 |
58 | ```html
59 |
Click Me!
60 | ```
61 |
62 | #### Changing Button Size
63 |
64 | Adjust the frame dimensions:
65 |
66 | ```css
67 | .frame {
68 | width: 200px;
69 | height: 200px;
70 | }
71 | ```
72 |
73 | ## License
74 |
75 | This project is open source and available under the MIT License.
76 |
77 | ## Contributing
78 |
79 | Feel free to fork this project and submit pull requests for improvements or new features!
80 |
81 | ## Author
82 |
83 | Created by [@BalintFerenczy](https://x.com/BalintFerenczy)
--------------------------------------------------------------------------------
/assets/base.svg:
--------------------------------------------------------------------------------
1 |
32 |
--------------------------------------------------------------------------------
/assets/button.svg:
--------------------------------------------------------------------------------
1 |
137 |
--------------------------------------------------------------------------------
/assets/cover.svg:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/assets/recolor-overlay.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 3D Pressable Button
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |

16 |

17 |
18 |
21 |
22 |

23 |
24 |
Button
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | .frame {
2 | position: relative;
3 |
4 | /* Button dimensions */
5 | width: 400px;
6 | height: 400px;
7 |
8 | /* Movement distances */
9 | --hover-travel: 3px;
10 | --press-travel: 40px;
11 |
12 | /* Color customization */
13 | --color: black;
14 | --brightness: 1;
15 | --blend-mode: color;
16 |
17 | /* Transition settings */
18 | --transition-duration: 0.4s;
19 | --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);
20 | }
21 |
22 | .frame, .recolor-overlay, .button, .text {
23 | user-select: none;
24 | }
25 |
26 | .base {
27 | width: 100%; height: 100%;
28 | }
29 |
30 | .recolor-overlay {
31 | position: absolute;
32 | width: 100%; height: 100%;
33 | color: var(--color);
34 | top: 0;
35 | left: 0;
36 | mix-blend-mode: var(--blend-mode);
37 |
38 | transition-property: all;
39 | transition-duration: var(--transition-duration);
40 | transition-timing-function: var(--transition-easing);
41 | }
42 |
43 | .button {
44 | position: absolute;
45 | width: 100%; height: 100%;
46 | top: 0;
47 | left: 0;
48 | filter: brightness(var(--brightness));
49 |
50 | transition-property: all;
51 | transition-duration: var(--transition-duration);
52 | transition-timing-function: var(--transition-easing);
53 | }
54 |
55 | .cover {
56 | position: absolute;
57 | top: 0;
58 | left: 0;
59 | width: 100%; height: 100%;
60 | }
61 |
62 | .frame:hover .button, .frame:hover .text, .frame:hover .recolor-overlay {
63 | margin-top: var(--hover-travel);
64 | }
65 |
66 | .frame:active .button, .frame:active .text, .frame:active .recolor-overlay {
67 | margin-top: var(--press-travel);
68 | }
69 |
70 | .text {
71 | font-family: sans-serif;
72 | font-size: 2rem;
73 | color: white;
74 | white-space: nowrap;
75 |
76 | position: absolute;
77 | width: 100%;
78 | height: 100%;
79 | top: 50%;
80 | left: 50%;
81 | text-align: center;
82 | align-content: center;
83 | translate: -50% -50%;
84 | transform: rotateY(0deg) rotateX(52.3deg) rotateZ(29deg) translateY(-28%) translateX(-16%);
85 | margin: 0px;
86 | padding: 0px;
87 |
88 | transition-property: all;
89 | transition-timing-function: var(--transition-easing);
90 | transition-duration: var(--transition-duration);
91 | }
--------------------------------------------------------------------------------