Back to Projects
Intermediate
Tip Calculator
Build a restaurant tip calculator that splits bills between friends. Practice forms, real-time calculations, and number formatting.
What You'll Learn
- How to read values from input fields in real time with the
inputevent - 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 ProjectSingle HTML file · All code included