How to Design a Calculator with Neumorphism Effect/Soft UI in JavaScript?

In this tutorial, we will create a calculator using JavaScript with a neumorphic effect, also known as soft UI. Neumorphism is a modern design trend characterized by soft, rounded edges and subtle inset/outset shadows that create a tactile, embossed appearance.

What is Neumorphism?

Neumorphism combines elements of skeuomorphism and flat design. It creates depth through subtle shadows and highlights, making UI elements appear to be extruded from or pressed into the background surface.

Planning the Calculator Layout

Our calculator will include:

  • Two input fields for entering numbers

  • One output field to display results

  • Operation buttons (+, -, *, /) with neumorphic styling

CSS Neumorphic Styling

The key to neumorphism is using box-shadow with both light and dark shadows:

  • Inset shadows for input fields (pressed appearance)

  • Outset shadows for buttons (raised appearance)

  • Light background colors (#fafafa) for contrast

Complete Calculator Implementation

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>Neumorphic Calculator</title>
   <style>
      body {
         background: #e0e5ec;
         font-family: Arial, sans-serif;
         padding: 50px;
      }
      
      /* Main Container */
      .container {
         display: grid;
         grid-template-columns: repeat(4, 1fr);
         gap: 20px;
         max-width: 400px;
         margin: 0 auto;
         padding: 30px;
         background: #e0e5ec;
         border-radius: 20px;
         box-shadow: 20px 20px 40px #bebebe, -20px -20px 40px #ffffff;
      }
      
      /* Input Fields - Inset Effect */
      .input, .input2, .output {
         grid-column: 1 / span 4;
         background: #e0e5ec;
         border: none;
         padding: 20px;
         font-size: 18px;
         border-radius: 15px;
         text-align: right;
         box-shadow: inset 8px 8px 15px #a3b1c6, inset -8px -8px 15px #ffffff;
         outline: none;
         margin-bottom: 10px;
      }
      
      .output {
         font-weight: bold;
         color: #2c3e50;
      }
      
      /* Buttons - Raised Effect */
      .button {
         background: #e0e5ec;
         border: none;
         padding: 20px;
         font-size: 18px;
         font-weight: bold;
         color: #2c3e50;
         border-radius: 15px;
         cursor: pointer;
         transition: all 0.1s ease;
         box-shadow: 8px 8px 15px #a3b1c6, -8px -8px 15px #ffffff;
      }
      
      .button:hover {
         box-shadow: 6px 6px 12px #a3b1c6, -6px -6px 12px #ffffff;
      }
      
      .button:active {
         box-shadow: inset 4px 4px 8px #a3b1c6, inset -4px -4px 8px #ffffff;
      }
      
      .operator {
         color: #3498db;
         font-weight: bold;
      }
   </style>
</head>
<body>
   <div class="container">
      <input type="text" class="input" placeholder="Enter first number">
      <input type="text" class="input2" placeholder="Enter second number">
      <input type="text" class="output" placeholder="Result" readonly>
      <button class="button operator">+</button>
      <button class="button operator">-</button>
      <button class="button operator">*</button>
      <button class="button operator">/</button>
   </div>
   
   <script>
      // Calculator function
      function calculate(num1, num2, operation) {
         switch (operation) {
            case '+':
               return num1 + num2;
            case '-':
               return num1 - num2;
            case '*':
               return num1 * num2;
            case '/':
               return num2 !== 0 ? num1 / num2 : 'Error';
            default:
               return 'Invalid operation';
         }
      }

      // Get DOM elements
      const input1 = document.querySelector('.input');
      const input2 = document.querySelector('.input2');
      const output = document.querySelector('.output');
      const buttons = document.querySelectorAll('.button');

      // Add click listeners to operation buttons
      buttons.forEach(button => {
         button.addEventListener('click', () => {
            const num1 = parseFloat(input1.value) || 0;
            const num2 = parseFloat(input2.value) || 0;
            const operation = button.textContent;
            
            const result = calculate(num1, num2, operation);
            output.value = result;
         });
      });

      // Clear output when inputs change
      input1.addEventListener('input', () => output.value = '');
      input2.addEventListener('input', () => output.value = '');
   </script>
</body>
</html>

Key Neumorphic Design Elements

Element Shadow Type Effect
Input Fields Inset shadows Pressed/carved appearance
Buttons Outset shadows Raised/extruded appearance
Container Large outset shadows Floating card effect

JavaScript Functionality

The calculator handles:

  • Basic arithmetic operations (+, -, *, /)

  • Division by zero error handling

  • Input validation using parseFloat()

  • Dynamic result updates on button clicks

Enhancing the Design

To improve the neumorphic effect:

  • Use consistent border-radius values (15-20px)

  • Apply smooth transitions for button interactions

  • Maintain subtle color contrast with the background

  • Add hover and active states for better UX

Conclusion

This neumorphic calculator demonstrates how CSS box-shadows can create depth and tactile appeal in modern web interfaces. The soft UI design trend offers an elegant alternative to flat design while maintaining clean, minimal aesthetics.

Updated on: 2026-03-15T23:19:00+05:30

305 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements