Create a browser-based calculator that evaluates chained expressions. This project reinforces functions, conditionals, and DOM event handling.

Requirements

  • HTML, CSS, and JavaScript fundamentals
  • Understanding of operators and functions
  • No external libraries

Features

  • Number buttons (0–9) and decimal point
  • Operators: +, , ×, ÷
  • = to evaluate, C to clear, to backspace
  • Display shows current input and result
  • Optional: keyboard support

Step 1: HTML Structure

Create calculator/ with index.html, style.css, and app.js.

  <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Calculator</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="calculator">
    <div id="display" class="display">0</div>
    <div class="buttons">
      <button data-action="clear">C</button>
      <button data-action="backspace">⌫</button>
      <button data-action="operator" data-value="/">÷</button>
      <button data-action="operator" data-value="*">×</button>
      <button data-action="number" data-value="7">7</button>
      <button data-action="number" data-value="8">8</button>
      <button data-action="number" data-value="9">9</button>
      <button data-action="operator" data-value="-">−</button>
      <button data-action="number" data-value="4">4</button>
      <button data-action="number" data-value="5">5</button>
      <button data-action="number" data-value="6">6</button>
      <button data-action="operator" data-value="+">+</button>
      <button data-action="number" data-value="1">1</button>
      <button data-action="number" data-value="2">2</button>
      <button data-action="number" data-value="3">3</button>
      <button data-action="equals" class="tall">=</button>
      <button data-action="number" data-value="0" class="wide">0</button>
      <button data-action="number" data-value=".">.</button>
    </div>
  </div>
  <script src="app.js"></script>
</body>
</html>
  

Step 2: Grid Layout

  .calculator { max-width: 320px; margin: 2rem auto; background: #222; border-radius: 12px; padding: 1rem; }
.display { background: #111; color: #fff; font-size: 2rem; text-align: right; padding: 1rem; border-radius: 8px; margin-bottom: 1rem; overflow: hidden; }
.buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; }
button { font-size: 1.25rem; padding: 1rem; border: none; border-radius: 8px; cursor: pointer; background: #444; color: #fff; }
button:hover { background: #555; }
.wide { grid-column: span 2; }
.tall { grid-row: span 2; }
  

Step 3: Calculator State

Track three values in app.js:

  let currentValue = '0';
let previousValue = '';
let operator = null;
let shouldResetDisplay = false;

const display = document.getElementById('display');

function updateDisplay() {
  display.textContent = currentValue;
}
  

Step 4: Input Handlers

  function inputNumber(num) {
  if (shouldResetDisplay) {
    currentValue = num;
    shouldResetDisplay = false;
  } else {
    currentValue = currentValue === '0' ? num : currentValue + num;
  }
  updateDisplay();
}

function inputDecimal() {
  if (shouldResetDisplay) { currentValue = '0.'; shouldResetDisplay = false; }
  else if (!currentValue.includes('.')) currentValue += '.';
  updateDisplay();
}

function selectOperator(op) {
  if (operator && !shouldResetDisplay) calculate();
  previousValue = currentValue;
  operator = op;
  shouldResetDisplay = true;
}
  

Step 5: Calculate and Clear

  function calculate() {
  if (!operator || shouldResetDisplay) return;
  const prev = parseFloat(previousValue);
  const curr = parseFloat(currentValue);
  let result;

  switch (operator) {
    case '+': result = prev + curr; break;
    case '-': result = prev - curr; break;
    case '*': result = prev * curr; break;
    case '/': result = curr === 0 ? 'Error' : prev / curr; break;
  }

  currentValue = String(result);
  operator = null;
  previousValue = '';
  shouldResetDisplay = true;
  updateDisplay();
}

function clearAll() {
  currentValue = '0';
  previousValue = '';
  operator = null;
  shouldResetDisplay = false;
  updateDisplay();
}
  

Step 6: Wire Up Buttons

  document.querySelector('.buttons').addEventListener('click', e => {
  const btn = e.target.closest('button');
  if (!btn) return;
  const action = btn.dataset.action;

  if (action === 'number') {
    btn.dataset.value === '.' ? inputDecimal() : inputNumber(btn.dataset.value);
  } else if (action === 'operator') selectOperator(btn.dataset.value);
  else if (action === 'equals') calculate();
  else if (action === 'clear') clearAll();
  else if (action === 'backspace') {
    currentValue = currentValue.length > 1 ? currentValue.slice(0, -1) : '0';
    updateDisplay();
  }
});
  

Extension Ideas

  • Keyboard support — map number keys, operators, Enter, Escape, and Backspace to the same handlers
  • Calculation history — show the last five operations below the display
  • Scientific mode — add sin, cos, sqrt buttons
  • Memory functions — M+, M−, MR, MC
  • Themes — light/dark toggle stored in localStorage