JavaScript Tutorial

JavaScript Project: Tip Calculator

Split a bill: bill amount, tip percent, and people. Show the tip and the total per person.

What you will build

A bill splitter. The visitor enters the bill, a tip percent, and how many people share the cost. The page shows the tip in currency and the total each person pays.

Money on a page is still a number in the script. You convert the three fields with Number, guard against empty or invalid input, then format the results with toFixed(2) so cents stay two digits.

Open an example with Try it in JavaScript. That loads /javascript/try — a live page and a console.

Methods you will use

MethodJob on this page
NumberTurns each field string into a numeric value
toFixedFormats tip and totals to two decimal places
input / .valueReads bill, percent, and people
isFiniteRejects empty fields, letters, and Infinity
clickRuns the split when the visitor asks for it

Number("") is 0. That would look like a free meal. Check the raw string first, then convert. People must be an integer of at least 1 or you would divide by zero.

Build in slices

Three labeled fields and a button. Use type="number" so the keypad on a phone is numeric. The results sit in two paragraphs you can fill later.

Example

<label for="bill">Bill amount</label>
<input id="bill" type="number" min="0" step="0.01" value="48.50">
<label for="percent">Tip percent</label>
<input id="percent" type="number" min="0" value="18">
<label for="people">People</label>
<input id="people" type="number" min="1" step="1" value="2">
<button id="split" type="button">Split the bill</button>
<p id="tip">Tip: —</p>
<p id="each">Each person: —</p>

Convert, validate, then compute. Tip is bill times percent over 100. Grand total is bill plus tip. Each person pays the grand total divided by people.

Example

function money(n) {
  return "$" + n.toFixed(2);
}

const bill = Number(document.getElementById("bill").value);
const percent = Number(document.getElementById("percent").value);
const people = Number(document.getElementById("people").value);

if (!isFinite(bill) || bill < 0 || !isFinite(percent) || percent < 0) {
  throw new Error("Bill and percent must be valid numbers.");
}
if (!Number.isInteger(people) || people < 1) {
  throw new Error("People must be a whole number of at least 1.");
}

const tip = bill * (percent / 100);
const each = (bill + tip) / people;
document.getElementById("tip").textContent = "Tip: " + money(tip);
document.getElementById("each").textContent = "Each person: " + money(each);

Wrap the math in a click handler and write errors onto the page instead of throwing. A calculator should not go silent when a field is blank.

Example

<label for="bill">Bill amount</label>
<input id="bill" type="number" min="0" step="0.01" value="48.50">
<label for="percent">Tip percent</label>
<input id="percent" type="number" min="0" value="18">
<label for="people">People</label>
<input id="people" type="number" min="1" step="1" value="2">
<button id="split" type="button">Split the bill</button>
<p id="tip">Tip: —</p>
<p id="each">Each person: —</p>
<script>
  function money(n) {
    return "$" + n.toFixed(2);
  }

  document.getElementById("split").addEventListener("click", function () {
    const bill = Number(document.getElementById("bill").value);
    const percent = Number(document.getElementById("percent").value);
    const people = Number(document.getElementById("people").value);
    const tipLine = document.getElementById("tip");
    const eachLine = document.getElementById("each");

    if (!isFinite(bill) || bill < 0 || !isFinite(percent) || percent < 0) {
      tipLine.textContent = "Enter a valid bill and tip percent.";
      eachLine.textContent = "Each person: —";
      return;
    }
    if (!Number.isInteger(people) || people < 1) {
      tipLine.textContent = "People must be a whole number of at least 1.";
      eachLine.textContent = "Each person: —";
      return;
    }

    const tip = bill * (percent / 100);
    const each = (bill + tip) / people;
    tipLine.textContent = "Tip: " + money(tip);
    eachLine.textContent = "Each person: " + money(each);
  });
</script>

Try 48.50, 18 percent, and 2 people at /javascript/try. The tip should be $8.73 and each person $28.62. Use Try it in JavaScript.

Complete document

This file is the splitter you would keep. Starting values match a restaurant bill so the first click has something to compute. The card stays in the yellow studio palette.

Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Tip Calculator</title>
  <style>
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      background: #fefce8;
      font-family: "Segoe UI", system-ui, sans-serif;
      color: #1c1917;
    }
    .card {
      width: min(22rem, 92vw);
      background: #fffbeb;
      border: 1px solid #fde68a;
      padding: 1.4rem 1.5rem 1.5rem;
    }
    h1 { margin: 0 0 0.9rem; font-size: 1.4rem; }
    label { display: block; font-weight: 700; margin: 0.55rem 0 0.3rem; }
    input {
      width: 100%;
      box-sizing: border-box;
      padding: 0.45rem 0.55rem;
      border: 1px solid #d6d3d1;
      font: inherit;
    }
    button {
      margin-top: 0.9rem;
      padding: 0.5rem 0.9rem;
      border: 0;
      background: #854d0e;
      color: #fffbeb;
      font: inherit;
      font-weight: 700;
      cursor: pointer;
    }
    .out {
      margin: 1rem 0 0;
      padding-top: 0.85rem;
      border-top: 1px solid #fde68a;
    }
    .out p { margin: 0.25rem 0; }
  </style>
</head>
<body>
  <article class="card">
    <h1>Tip Calculator</h1>
    <label for="bill">Bill amount</label>
    <input id="bill" type="number" min="0" step="0.01" value="48.50">
    <label for="percent">Tip percent</label>
    <input id="percent" type="number" min="0" value="18">
    <label for="people">People</label>
    <input id="people" type="number" min="1" step="1" value="2">
    <button id="split" type="button">Split the bill</button>
    <div class="out">
      <p id="tip">Tip: —</p>
      <p id="total">Grand total: —</p>
      <p id="each">Each person: —</p>
    </div>
  </article>
  <script>
    function money(n) {
      return "$" + n.toFixed(2);
    }

    function showError(text) {
      document.getElementById("tip").textContent = text;
      document.getElementById("total").textContent = "Grand total: —";
      document.getElementById("each").textContent = "Each person: —";
    }

    document.getElementById("split").addEventListener("click", function () {
      const bill = Number(document.getElementById("bill").value);
      const percent = Number(document.getElementById("percent").value);
      const people = Number(document.getElementById("people").value);

      if (!isFinite(bill) || bill < 0 || !isFinite(percent) || percent < 0) {
        showError("Enter a valid bill and tip percent.");
        return;
      }
      if (!Number.isInteger(people) || people < 1) {
        showError("People must be a whole number of at least 1.");
        return;
      }

      const tip = bill * (percent / 100);
      const grand = bill + tip;
      const each = grand / people;
      document.getElementById("tip").textContent = "Tip: " + money(tip);
      document.getElementById("total").textContent = "Grand total: " + money(grand);
      document.getElementById("each").textContent = "Each person: " + money(each);
    });
  </script>
</body>
</html>

Rounding and split bills

toFixed(2) returns a string, which is what you want for display. Do the division on the raw numbers first. If you format the tip, then parse it back, you can lose a cent on some totals.

Real restaurants sometimes round the last person up. This page splits evenly and lets the last cent sit in the formatted string. That is enough for the project.

Common mistakes

  • Using parseInt on the bill. $48.50 becomes 48 and the tip is short.
  • Dividing by people without checking it is at least 1. Zero people is not a table.
  • Writing percent / 100 as percent / 10. Eighteen percent would become 1.8 times the bill.
  • Showing the tip as a raw float like 8.7300000001. Always format money.
  • Listening to submit on a form with no preventDefault. The page reloads and the result vanishes.

Practice tasks

  1. Recalculate on every input event so the visitor does not need the button.
  2. Add a 15 / 18 / 20 percent row of buttons that fill the percent field and split immediately.
  3. Show the bill per person without tip as a fourth line. Preview at /javascript/try.

FAQ: JavaScript Project: Tip Calculator

Common questions about this page.

What is the StudyGrid JavaScript tutorial?

The StudyGrid JavaScript tutorial is a full beginner track: variables, functions, arrays, if/else, the DOM, events, storage, and fetch. Each chapter has copy-and-run examples.

Should I run javascript tip project examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn javascript tip project in this JavaScript JavaScript lesson (JavaScript Project: Tip Calculator).

Is the JavaScript editor the same as Try Python?

No. Try JavaScript is a live page plus a console at /javascript/try. Try Python stays at /try. JavaScript lessons never open the Python editor.

Do I need to install anything to learn JavaScript?

No. Open a chapter, click Try it in JavaScript, and the page and console update in the browser.

Where should I start the JavaScript tutorial?

Start at JavaScript Intro, then Where To, Output, and Syntax. After variables and functions, continue to the DOM and events. Use Next at the bottom of each chapter.

Is the JavaScript tutorial free?

Yes. The JavaScript studio on StudyGrid (studygrid.in) is free: dashboard, chapters, and the live editor.