Back to Projects Intermediate

Tip Calculator

Build a restaurant tip calculator that splits bills between friends. Practice forms, real-time calculations, and number formatting.

HTML, CSS, JavaScript ~1-2 hours to build Free source code

What You'll Learn

  • How to read values from input fields in real time with the input event
  • How to do percentage calculations with JavaScript
  • How to format numbers as currency using toFixed()
  • How to validate user input and handle edge cases (like dividing by zero)
  • How to update multiple parts of the page simultaneously

How It Works

Get the bill amount and tip percentage

The user enters the total bill and picks a tip percentage. We read these values from form inputs every time they change using the input event listener.

Do the math

Tip = bill × (tip% / 100). Total = bill + tip. Per person = total / people. Three simple calculations give us everything to display.

Show results instantly

We use the 'input' event so results update as the user types — no button press needed. This makes the app feel modern and responsive.

Source Code

HTML Structure

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Tip Calculator</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="calc-card">
    <h1><span>💰</span> Tip Calculator</h1>
    <div class="input-group">
      <label>Bill Amount ($)</label>
      <input type="number" id="bill" placeholder="0.00" min="0">
    </div>
    <div class="input-group">
      <label>Select Tip %</label>
      <div class="tip-btns">
        <button class="tip-btn" data-tip="10">10%</button>
        <button class="tip-btn" data-tip="15">15%</button>
        <button class="tip-btn active" data-tip="20">20%</button>
        <button class="tip-btn" data-tip="25">25%</button>
      </div>
    </div>
    <div class="input-group">
      <label>Number of People</label>
      <input type="number" id="people" placeholder="1" min="1" value="1">
    </div>
    <div class="results">
      <div class="result-row"><span>Tip Amount</span><span id="tipAmount">$0.00</span></div>
      <div class="result-row"><span>Total</span><span id="totalAmount">$0.00</span></div>
      <div class="result-row highlight"><span>Per Person</span><span id="perPerson">$0.00</span></div>
    </div>
    <button id="resetBtn">Reset</button>
  </div>
  <script src="script.js"></script>
</body>
</html>

CSS Styling

CSS
* { margin:0; padding:0; box-sizing:border-box; }
body { min-height:100vh; display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg,#0d3b8a,#2980b9); font-family:'Segoe UI',sans-serif; padding:20px; }
.calc-card { background:white; border-radius:24px; padding:36px; width:100%; max-width:420px;
  box-shadow:0 20px 60px rgba(0,0,0,0.25); }
h1 { text-align:center; color:#25265e; margin-bottom:28px; font-size:1.6rem; }
.input-group { margin-bottom:20px; }
label { display:block; font-size:0.85rem; font-weight:600; color:#555; margin-bottom:8px;
  text-transform:uppercase; letter-spacing:0.5px; }
input { width:100%; padding:14px 16px; border:2px solid #e0e0e0; border-radius:10px;
  font-size:1rem; outline:none; transition:border-color 0.2s; color:#333; }
input:focus { border-color:#2980b9; }
.tip-btns { display:grid; grid-template-columns:repeat(4,1fr); gap:8px; }
.tip-btn { padding:12px; border:2px solid #e0e0e0; border-radius:8px; background:white;
  font-weight:700; font-size:0.95rem; cursor:pointer; transition:all 0.2s; color:#333; }
.tip-btn.active, .tip-btn:hover { background:#2980b9; border-color:#2980b9; color:white; }
.results { background:#f0f7ff; border-radius:16px; padding:24px; margin:24px 0; }
.result-row { display:flex; justify-content:space-between; align-items:center;
  padding:10px 0; border-bottom:1px solid rgba(41,128,185,0.1); color:#555; font-size:0.95rem; }
.result-row:last-child { border:none; }
.result-row span:last-child { font-weight:700; font-size:1rem; color:#25265e; }
.result-row.highlight span:last-child { font-size:1.4rem; color:#2980b9; }
#resetBtn { width:100%; padding:14px; background:#25265e; color:white; border:none;
  border-radius:10px; font-weight:700; font-size:1rem; cursor:pointer; }
#resetBtn:hover { background:#1a1b4b; }

JavaScript Logic

JavaScript
let tipPercent = 20;

document.querySelectorAll('.tip-btn').forEach(btn => {
  btn.addEventListener('click', function() {
    document.querySelectorAll('.tip-btn').forEach(b => b.classList.remove('active'));
    this.classList.add('active');
    tipPercent = parseInt(this.dataset.tip);
    calculate();
  });
});

document.getElementById('bill').addEventListener('input', calculate);
document.getElementById('people').addEventListener('input', calculate);

function calculate() {
  const bill = parseFloat(document.getElementById('bill').value) || 0;
  const people = Math.max(parseInt(document.getElementById('people').value) || 1, 1);
  const tip = bill * (tipPercent / 100);
  const total = bill + tip;
  document.getElementById('tipAmount').textContent = `$${tip.toFixed(2)}`;
  document.getElementById('totalAmount').textContent = `$${total.toFixed(2)}`;
  document.getElementById('perPerson').textContent = `$${(total / people).toFixed(2)}`;
}

document.getElementById('resetBtn').addEventListener('click', () => {
  document.getElementById('bill').value = '';
  document.getElementById('people').value = 1;
  document.getElementById('tipAmount').textContent = '$0.00';
  document.getElementById('totalAmount').textContent = '$0.00';
  document.getElementById('perPerson').textContent = '$0.00';
});

Download Source Code

Single ready-to-run HTML file. Open it in any browser instantly!

Download Project

Single HTML file · All code included