Split Payment Calculator — Bill Splitter HTML CSS JS

Split Payment Calculator · Forms · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Tip presets with custom override
Four quick percentages plus a custom field, kept mutually exclusive so the UI never shows a contradictory selected state.
Bounded people stepper
Clamped between 2 and 20 people, with the relevant button disabled at each boundary.
Uneven split with live validation
Per-person percentage inputs default to an even split and are validated to sum to exactly 100% before showing dollar amounts.
Specific, actionable error messages
An invalid share total shows exactly what it currently sums to, not just a generic "invalid" message.
Single calculate() function
Every input change re-runs one calculation function, keeping subtotal, tip, total, and per-person output always in sync.
Tip included in per-person amounts
Uneven-split percentages apply to the grand total (bill + tip), not just the pre-tip subtotal, matching real-world bill splitting.
Auto-rebuilding share inputs
Changing the headcount while uneven mode is active regenerates the right number of percentage fields automatically.
Currency-formatted output throughout
Every dollar amount displays with toFixed(2), reading like real currency instead of a raw floating-point number.

About this UI Snippet

Split Payment Calculator — Tip Presets, People Stepper & Validated Uneven Split

Screenshot of the Split Payment Calculator snippet rendered live

Splitting a restaurant bill fairly is simple math that's annoying to do by hand, especially with a tip and an odd number of people — which is exactly why every group-dinner app ships some version of this calculator. This snippet builds a complete bill splitter: quick tip presets with a custom override, a people stepper, an even split by default, and an optional uneven-split mode that validates percentages sum to 100% before showing per-person amounts.

Tip presets that share state with a custom field

Four preset buttons (0/15/18/20%) and a custom number input all write to the same tipPct variable. Clicking a preset clears the custom field and highlights the matching button; typing in the custom field clears every preset's active state instead — so the UI never shows a highlighted preset that disagrees with a manually typed percentage, a small consistency detail that's easy to get wrong when two inputs can set the same value.

A people stepper with sane bounds

The stepper clamps between 2 and 20 people, disabling the relevant button at each boundary rather than letting the count go to 1 (at which point "splitting" stops meaning anything) or to an unreasonably large number. Every increment or decrement immediately recalculates the per-person amount and, if uneven mode is active, regenerates the share-percentage inputs for the new headcount.

Uneven split with real validation

Toggling "Uneven split" reveals one percentage input per person, defaulting to an even 100 / people split that's then free to be adjusted. calculate() sums every entered percentage and refuses to show per-person dollar amounts until that sum rounds to exactly 100% — instead surfacing a specific error ("Shares add up to 92% — should total 100%") so the user knows exactly how far off they are, rather than silently showing wrong numbers or blocking the whole calculator.

One calculate function, every output

Every visible number — subtotal, tip, grand total, and the per-person breakdown in both modes — flows through a single calculate() call triggered by every relevant input. There's no per-field update logic to keep in sync; changing the bill total, the tip, the people count, or any individual share simply re-runs the same function against the current state.

Rounding, the part most bill splitters get wrong

Dividing a grand total evenly across several people in floating-point arithmetic can leave the displayed shares off by a cent from the actual total — three people splitting $10.00 each get $3.33, and $3.33 × 3 is $9.99, not $10.00. This demo accepts that tiny float-formatting reality for clarity; a finance-grade version should round every share with toFixed(2), sum the rounded values, and silently add or subtract the few-cent remainder to the largest share so the displayed numbers always reconcile exactly with the bill.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't need to trace how tip presets, the custom field, and calculate() all stay reconciled by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how buildUnevenList regenerates share inputs defaulted to an even percentage, or why the uneven-split validation checks that shares round to exactly 100 rather than checking for an exact float match. The same assistant can help optimize it, for example flagging the floating-point rounding issue called out in the FAQ, where per-person shares can be a cent off from the actual total, and walking through the largest-remainder fix. It's also useful for extending the feature: ask it to add a split-by-dollar-amount mode as an alternative to percentages, support multiple currencies with toLocaleString, or add a "round up to the nearest dollar" tip button that back-solves the required percentage. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a bill-splitting calculator with tip presets, a people stepper, and an uneven-split mode in plain HTML, CSS, and JavaScript, no framework, no libraries.

Requirements:
- A bill total number input, four preset tip percentage buttons plus one custom percentage input, all writing to a single shared tip percentage variable. Selecting a preset must clear the custom input and highlight only that preset; typing in the custom input must clear every preset's highlighted state, so the UI never shows a highlighted preset that disagrees with a typed value.
- A plus/minus stepper for the number of people splitting, clamped between 2 and 20, disabling the relevant button at each boundary.
- A single calculate function that recomputes the subtotal, tip amount, and grand total on every relevant input change, and formats every dollar amount to exactly two decimal places.
- A toggleable "uneven split" mode that, when enabled, generates one percentage input per person defaulting to an even share (100 divided by the person count), and regenerates that list automatically whenever the person count changes while the mode is active.
- In uneven mode, sum all entered percentages and refuse to display any per-person dollar amounts unless that sum rounds to exactly 100 — instead show a specific message stating what the shares currently sum to, not a generic invalid-input message.
- Apply each person's percentage share to the grand total (bill plus tip), not just the pre-tip subtotal, so tip is distributed proportionally along with the bill.
- As a documented improvement in a code comment, describe the largest-remainder rounding technique needed to make individually-rounded per-person shares sum exactly back to the grand total instead of being off by a cent due to floating-point division.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA bill-splitting card renders with a $186.40 example total, an 18% tip selected, and a 4-person even split.
  2. 2
    Adjust the bill total or tipEdit the total field or pick a different tip preset (or type a custom percentage) — the subtotal, tip, and total update instantly.
  3. 3
    Change the headcountUse the +/− stepper to change how many people are splitting; the per-person amount recalculates immediately.
  4. 4
    Turn on uneven splitCheck "Uneven split" to reveal a percentage input per person, defaulting to an even share.
  5. 5
    Adjust individual sharesChange any person's percentage — if the total doesn't sum to 100%, an error shows exactly how far off it is instead of a wrong dollar amount.
  6. 6
    Fix the shares to see amountsOnce the percentages sum to 100%, each person's exact dollar share (including their portion of the tip) displays.

Real-world uses

Common Use Cases

Restaurant and group dining apps
The classic "split the check" feature for any dining, delivery, or expense-sharing app.
Roommate and shared-expense tools
Use uneven split mode for rent or utility bills where shares aren't meant to be equal.
Trip and event cost-sharing
Split a shared Airbnb, car rental, or group-event cost among attendees with flexible per-person shares.
Expense-tracking and budgeting apps
Pair with a budget tracker card to log a split bill against a category.
Payment app "request money" flows
Calculate exact amounts to request from each person before generating individual payment requests.
Learning validated multi-input forms
A clear example of cross-field validation (percentages summing to 100%) — compare with a tip calculator for the single-payer case.

Got questions?

Frequently Asked Questions

Floating-point per-person division can leave the sum off by a cent due to rounding; compute every person's amount with toFixed(2), sum those rounded values, and add or subtract the few-cent difference to/from the largest share so the displayed amounts reconcile exactly with the grand total.

Add a toggle between "percentage" and "dollar amount" modes for the uneven-split inputs; in dollar mode, validate that the entered amounts sum to the grand total (with the same actionable error message pattern) instead of validating percentages summing to 100%.

Replace the hardcoded "$" in the input wrapper and output strings with a currency symbol from a selected locale, and use toLocaleString(locale, { style: 'currency', currency }) instead of a manual "$" + toFixed(2) concatenation for correct formatting per currency.

Add a button that computes the tip percentage needed to make the grand total a round number (Math.ceil(total) - total, converted to a percentage of the subtotal) and calls setTip() with that computed value.

In React, keep total, tipPct, people, and an array of share percentages in useState and derive every output with useMemo; in Vue, use ref()/computed(); in Angular, use component fields with getters. The 100%-sum validation logic ports directly into each framework's reactive model.