Back
Learn how to build a tactile, three-dimensional button with shadows, highlights, and satisfying press animation using CSS transforms.
<div class="button-container"> <button class="btn-3d">Click Me</button> </div>The button text can be customized to match your specific call-to-action.
.button-container { display: flex; justify-content: center; align-items: center; }Next, we define the 3D button with CSS variables for easy customization:
.btn-3d { --button-color: #4F46E5; --button-color-dark: #3730A3; --button-color-light: #818CF8; --button-text: white; --button-height: 12px; --button-radius: 8px; --button-padding: 16px 32px; --button-font-size: 16px; position: relative; font-family: system-ui, -apple-system, sans-serif; font-weight: 600; font-size: var(--button-font-size); color: var(--button-text); background-color: var(--button-color); border: none; border-radius: var(--button-radius); padding: var(--button-padding); cursor: pointer; box-shadow: /* Bottom edge */ 0 var(--button-height) 0 var(--button-color-dark), /* Subtle inner highlight */ inset 0 1px 0 var(--button-color-light), /* Dark bottom shadow */ 0 calc(var(--button-height) + 2px) 0 rgba(0, 0, 0, 0.2); transform: translateY(0); transition: transform 0.15s ease, box-shadow 0.15s ease; user-select: none; }The key properties here: - We define three shades of our button color (main, dark, and light) to create the 3D effect - The box-shadow property creates multiple shadows: one for the bottom edge, one for the inner highlight, and one for the ground shadow - We set a faster transition time (0.15s) for a snappier press feel - user-select: none prevents text selection when clicking rapidly Next, we create the hover and active states:
.btn-3d:hover { background-color: #4338CA; } .btn-3d:active { transform: translateY(var(--button-height)); box-shadow: /* Flattened bottom edge */ 0 0 0 var(--button-color-dark), /* Maintain inner highlight */ inset 0 1px 0 var(--button-color-light), /* Reduced bottom shadow */ 0 2px 0 rgba(0, 0, 0, 0.2); }The active state is the heart of our 3D effect: - It translates the button down by the button-height amount - It changes the box-shadow to flatten the bottom edge (0 0 0) - It reduces the ground shadow to complete the pressed look To create the visible side edge of the button, we use a pseudo-element:
.btn-3d::before { content: ''; position: absolute; left: 0; right: 0; bottom: calc(-1 * var(--button-height)); height: var(--button-height); background-color: var(--button-color-dark); border-bottom-left-radius: var(--button-radius); border-bottom-right-radius: var(--button-radius); transition: background-color 0.15s ease; } .btn-3d:hover::before { background-color: #3730A3; } .btn-3d:active::before { height: 0; }This pseudo-element creates the visible side/edge of the button. When the button is pressed (active), the height becomes 0 to complete the illusion of the button being pressed down. Finally, we add focus styles for accessibility:
/* Focus state for accessibility */ .btn-3d:focus { outline: none; box-shadow: 0 var(--button-height) 0 var(--button-color-dark), inset 0 1px 0 var(--button-color-light), 0 calc(var(--button-height) + 2px) 0 rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(79, 70, 229, 0.3); } .btn-3d:active:focus { box-shadow: 0 0 0 var(--button-color-dark), inset 0 1px 0 var(--button-color-light), 0 2px 0 rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(79, 70, 229, 0.3); }These focus styles add a subtle outline around the button for keyboard navigation while maintaining the 3D effect for both the normal and pressed states. This 3D button offers several advantages: - Tactile feedback: The press animation provides a physical-feeling response to interaction. - Depth perception: The multiple shadows and highlights create a realistic sense of depth. - Visual engagement: The button stands out on the page and clearly communicates its interactive nature. - Playful interaction: The satisfying press effect adds a touch of playfulness to your interface. - Accessibility: Despite its stylized appearance, it maintains keyboard focus visibility. This button style is ideal for gaming interfaces, children's websites, interactive educational platforms, or any application where you want to create a more tangible, physical-feeling interaction.
<div class="button-container"> <button class="btn-3d">Click Me</button> </div> <style> .button-container { display: flex; justify-content: center; align-items: center; } .btn-3d { --button-color: #4F46E5; --button-color-dark: #3730A3; --button-color-light: #818CF8; --button-text: white; --button-height: 12px; --button-radius: 8px; --button-padding: 16px 32px; --button-font-size: 16px; position: relative; font-family: system-ui, -apple-system, sans-serif; font-weight: 600; font-size: var(--button-font-size); color: var(--button-text); background-color: var(--button-color); border: none; border-radius: var(--button-radius); padding: var(--button-padding); cursor: pointer; box-shadow: /* Bottom edge */ 0 var(--button-height) 0 var(--button-color-dark), /* Subtle inner highlight */ inset 0 1px 0 var(--button-color-light), /* Dark bottom shadow */ 0 calc(var(--button-height) + 2px) 0 rgba(0, 0, 0, 0.2); transform: translateY(0); transition: transform 0.15s ease, box-shadow 0.15s ease; user-select: none; } .btn-3d:hover { background-color: #4338CA; } .btn-3d:active { transform: translateY(var(--button-height)); box-shadow: /* Flattened bottom edge */ 0 0 0 var(--button-color-dark), /* Maintain inner highlight */ inset 0 1px 0 var(--button-color-light), /* Reduced bottom shadow */ 0 2px 0 rgba(0, 0, 0, 0.2); } .btn-3d::before { content: ''; position: absolute; left: 0; right: 0; bottom: calc(-1 * var(--button-height)); height: var(--button-height); background-color: var(--button-color-dark); border-bottom-left-radius: var(--button-radius); border-bottom-right-radius: var(--button-radius); transition: background-color 0.15s ease; } .btn-3d:hover::before { background-color: #3730A3; } .btn-3d:active::before { height: 0; } /* Focus state for accessibility */ .btn-3d:focus { outline: none; box-shadow: 0 var(--button-height) 0 var(--button-color-dark), inset 0 1px 0 var(--button-color-light), 0 calc(var(--button-height) + 2px) 0 rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(79, 70, 229, 0.3); } .btn-3d:active:focus { box-shadow: 0 0 0 var(--button-color-dark), inset 0 1px 0 var(--button-color-light), 0 2px 0 rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(79, 70, 229, 0.3); } </style>Thank you for reading this article.
Comments
No comments yet. Be the first to comment!