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)