Back

Creating a 3D Button with Realistic Press Effect

Learn how to build a tactile, three-dimensional button with shadows, highlights, and satisfying press animation using CSS transforms.

HTML

The HTML structure for our 3D button is very simple - just a container div and a button element with the class btn-3d.
        <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.

CSS

First, we set up the container to center our button:
        .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.

Whole code

<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!

More buttons

Similar

See also