Let's create a modern calculator that's both beautiful and functional, with all the code explained in an engaging way. By the end, you'll have a calculator that works on all devices and even supports keyboard input!
🎨 The Design Vision
We're building a calculator with:
- A dark theme (with easy light mode potential)
- Full calculation history
- Keyboard support (type directly!)
- Responsive design (works on phones too)
- Smooth animations
🛠️ Let's Build It!
1. The HTML Foundation
Our calculator needs:
- A display area (for current input and history)
- Number buttons (0-9)
- Operator buttons (+, -, *, /)
- Special functions (AC, DEL, %)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Calculator</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="calculator">
<!-- Display Area -->
<div class="display">
<div class="history"></div>
<input type="text" id="output" readonly>
</div>
<!-- Buttons Grid -->
<div class="buttons">
<button data-value="AC" class="ac">AC</button>
<button data-value="DEL" class="del">DEL</button>
<button data-value="%" class="operator">%</button>
<button data-value="/" class="operator">÷</button>
<button data-value="7" class="number">7</button>
<button data-value="8" class="number">8</button>
<button data-value="9" class="number">9</button>
<button data-value="*" class="operator">×</button>
<button data-value="4" class="number">4</button>
<button data-value="5" class="number">5</button>
<button data-value="6" class="number">6</button>
<button data-value="-" class="operator">−</button>
<button data-value="1" class="number">1</button>
<button data-value="2" class="number">2</button>
<button data-value="3" class="number">3</button>
<button data-value="+" class="operator">+</button>
<button data-value="0" class="number zero">0</button>
<button data-value="." class="number">.</button>
<button data-value="=" class="equals">=</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Key Points:
-
data-value
attributes store what each button does - Special classes like
operator
andnumber
help with styling - The zero button is wider (we'll style it that way)
2. Stylish CSS Makeover
Let's give our calculator some personality with:
- A sleek dark theme
- Glowing operator buttons
- Smooth button presses
:root {
--bg-color: #1e1e2e;
--display-bg: #2a2a3a;
--button-bg: #3a3a4a;
--operator-color: #ff9500;
--equals-color: #ff2d75;
--ac-del-color: #a5a5a5;
--text-color: #ffffff;
}
body {
background: var(--bg-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Segoe UI', sans-serif;
transition: all 0.3s ease;
}
.calculator {
width: 320px;
background: var(--bg-color);
border-radius: 20px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.display {
background: var(--display-bg);
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
text-align: right;
}
.history {
color: rgba(255, 255, 255, 0.5);
height: 20px;
font-size: 14px;
}
#output {
width: 100%;
border: none;
background: transparent;
color: var(--text-color);
font-size: 36px;
text-align: right;
outline: none;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
button {
height: 60px;
border: none;
border-radius: 10px;
font-size: 24px;
cursor: pointer;
transition: all 0.1s;
color: var(--text-color);
background: var(--button-bg);
}
button:active {
transform: scale(0.95);
}
.number {
background: var(--button-bg);
}
.operator {
background: var(--operator-color);
}
.equals {
background: var(--equals-color);
}
.ac, .del {
background: var(--ac-del-color);
}
.zero {
grid-column: span 2;
}
/* Glow effect on hover */
.operator:hover, .equals:hover {
filter: brightness(1.2);
box-shadow: 0 0 10px currentColor;
}
Design Highlights:
- CSS variables make theme changes easy
- Grid layout for perfect button alignment
- Interactive button effects (press and glow)
- The zero button spans two columns
3. JavaScript Magic
Now for the brains! Our calculator needs to:
- Handle button clicks
- Manage calculations
- Support keyboard input
- Show history
const output = document.getElementById('output');
const buttons = document.querySelectorAll('button');
const historyDisplay = document.querySelector('.history');
let currentInput = '0';
let calculationHistory = '';
// Initialize display
output.value = currentInput;
// Update the calculator display
function updateDisplay() {
output.value = currentInput;
// Adjust font size for long numbers
output.style.fontSize = currentInput.length > 12 ? '24px' : '36px';
}
// Check if input is valid
function isValidInput(value) {
// Prevent multiple decimals
if (value === '.' && currentInput.includes('.') && !'+-*/'.includes(currentInput.slice(-1))) {
return false;
}
// Prevent consecutive operators
if ('+-*/'.includes(value) && '+-*/'.includes(currentInput.slice(-1))) {
return false;
}
return true;
}
// Perform the calculation
function calculate() {
try {
// Replace × and ÷ with * and /
let expression = currentInput.replace(/×/g, '*').replace(/÷/g, '/');
// Use Function constructor instead of eval
const result = new Function(`return ${expression}`)();
// Format the result
return Number.isInteger(result) ? result.toString() : result.toFixed(4);
} catch {
return 'Error';
}
}
// Handle button clicks
buttons.forEach(button => {
button.addEventListener('click', () => {
const value = button.dataset.value;
if (value === 'AC') {
// Clear everything
currentInput = '0';
calculationHistory = '';
historyDisplay.textContent = '';
} else if (value === 'DEL') {
// Backspace functionality
currentInput = currentInput.length > 1 ? currentInput.slice(0, -1) : '0';
} else if (value === '=') {
// Calculate and show history
calculationHistory = currentInput;
historyDisplay.textContent = calculationHistory + ' =';
currentInput = calculate();
} else {
// Add numbers or operators
if (!isValidInput(value)) return;
if (currentInput === '0' && !'+-*/'.includes(value)) {
currentInput = value;
} else {
currentInput += value;
}
}
updateDisplay();
});
});
// Keyboard support
document.addEventListener('keydown', (e) => {
const keyMap = {
'Enter': '=',
'Backspace': 'DEL',
'Escape': 'AC',
'*': '*',
'+': '+',
'-': '-',
'/': '/',
'%': '%',
'.': '.'
};
if (keyMap[e.key]) {
document.querySelector(`button[data-value="${keyMap[e.key]}"]`).click();
} else if (!isNaN(e.key) || e.key === '0') {
document.querySelector(`button[data-value="${e.key}"]`).click();
}
});
Key Features:
- Safe calculations using Function instead of eval
- Input validation prevents errors
- Keyboard support for quick typing
- History tracking shows your previous calculation
- Error handling for invalid expressions
🚀 Taking It Further
Want to enhance your calculator? Try these ideas:
- Add Light/Dark Mode Toggle
const themeToggle = document.createElement('button');
themeToggle.textContent = '🌙';
document.body.prepend(themeToggle);
themeToggle.addEventListener('click', () => {
document.body.classList.toggle('light-mode');
});
Add to CSS:
.light-mode {
--bg-color: #f0f2f5;
--display-bg: #ffffff;
--button-bg: #e0e0e0;
--text-color: #000000;
}
- Add Scientific Functions
<button data-value="Math.sqrt(">√</button>
<button data-value="Math.pow(,2)">x²</button>
- Add Memory Functions
let memory = 0;
function memoryAdd() {
memory += parseFloat(currentInput);
}
💡 Why This Calculator Rocks
- No eval() - Safer calculations using Function constructor
- Great UX - Visual feedback on button presses
- Responsive - Works on any device
- Accessible - Works with keyboard and screen readers
- Easy to Extend - Add more features easily
Now you've got a calculator that looks great and works even better! What feature will you add next? Maybe voice control or calculation graphs? The possibilities are endless!
Top comments (0)