1
Fork 0
A working tip calculator in one HTML file, one CSS file, and 30 lines of JavaScript. https://devai.io/templates/tip-calculator
  • CSS 41.7%
  • JavaScript 29.8%
  • HTML 25.8%
  • Dockerfile 2.7%
Find a file Use this template
Leonardo Devai 5444d48b9a Standardize projects: compose.yaml, ./data state, CI workflow, GUIDELINES
Checkpoint of the in-progress standardization pass (2026-07-20) before the git.devai.io split.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01128fhuZbgivaSJvtMf4s1G
2026-09-27 20:07:30 +02:00
.github/workflows Standardize projects: compose.yaml, ./data state, CI workflow, GUIDELINES 2026-09-27 20:07:30 +02:00
.dockerignore Add the devai.io boilerplate library: 42 runnable projects 2026-07-19 16:31:48 +02:00
.gitignore Standardize projects: compose.yaml, ./data state, CI workflow, GUIDELINES 2026-09-27 20:07:30 +02:00
app.js Add the devai.io boilerplate library: 42 runnable projects 2026-07-19 16:31:48 +02:00
compose.yaml Standardize projects: compose.yaml, ./data state, CI workflow, GUIDELINES 2026-09-27 20:07:30 +02:00
Dockerfile Add the devai.io boilerplate library: 42 runnable projects 2026-07-19 16:31:48 +02:00
index.html Add the devai.io boilerplate library: 42 runnable projects 2026-07-19 16:31:48 +02:00
README.md Standardize projects: compose.yaml, ./data state, CI workflow, GUIDELINES 2026-09-27 20:07:30 +02:00
styles.css Add the devai.io boilerplate library: 42 runnable projects 2026-07-19 16:31:48 +02:00

tip-calculator

A working tip calculator in one HTML file, one CSS file, and 30 lines of JavaScript.

What you'll build: a little app where you type a bill amount, drag a slider to pick a tip percentage, say how many people are splitting it, and instantly see the tip and the total each person owes.

What you'll learn: the single most important pattern in web pages — read the inputs → do some math → write the answer back onto the screen — and how to make it happen automatically every time something changes.

Run it

The easy way: double-click index.html. It opens in your browser and works. There is nothing to install and no build step.

Or serve it like production:

docker compose up --build   # then open http://localhost:8080

The idea in 30 seconds

A web page is just text (HTML) with styling (CSS). JavaScript is what makes it react. Here the whole app is one function, calculate(), that:

  1. reads the three input boxes,
  2. multiplies to get the tip and divides to get the per-person total,
  3. drops those numbers back into the page.

We tell the browser: "run calculate() every time any input changes." That's it. There is no framework and no magic.

How the code works

  • index.html lays out the boxes. Each input has an id (like id="bill") so JavaScript can find it.
  • app.js does three things:
    • document.getElementById("bill") grabs an element by its id.
    • parseFloat(...) turns the text you typed into a number we can do math with.
    • Intl.NumberFormat is a built-in that formats 19.5 as $19.50 for us.
    • addEventListener("input", calculate) is the key line — "whenever this box changes, run calculate."
  • styles.css is plain CSS. The @media (prefers-color-scheme: light) block swaps the colors if the visitor's device is in light mode.

Try changing something

  • Change the currency: swap "USD" for "EUR" (and "en-US" for "de-DE").
  • Add a "round up to the nearest dollar" checkbox.
  • Change the slider's max="30" to max="50" for the generous tippers.

Files

index.html      the boxes and labels
styles.css      how it looks (light + dark)
app.js          the 30 lines that make it work
Dockerfile      optional: serve it with nginx
compose.yaml    optional: docker compose up --build

Deploy

Push to your own GitHub repo and the shipped workflow (.github/workflows/ci.yml) tests the compose stack, publishes the image to GHCR, and — once you set the DEPLOY_HOST / DEPLOY_USER variables and DEPLOY_KEY secret — deploys it to your server over ssh.


Part of devai.io — the Web Basics track: HTML, CSS & JavaScript, one concept at a time.