Formatting Currency And Split
Section overview
We will now improve our tip calculator by formatting currency values to look professional, and making the split counter display proper grammar (1 person vs 2 people).
You'll learn how to create reusable helper functions, format numbers with decimals, and use JavaScript's built-in internationalization API for currency formatting.
The formatting problem
Currently, our calculator displays raw numbers that can look messy:
- Values like
15.666666666667instead of$15.67 - No dollar sign to indicate currency
- "1 people" instead of "1 person"
Let's fix these issues to make our calculator more user-friendly!
Creating a currency formatting function
We'll create a helper function that takes a number and returns a formatted currency string. Add this function above your update function:
function formatMoney(value) {
value = Math.ceil(value * 100) / 100;
value = value.toFixed(2);
return '$ ' + value;
}
function update() {
// existing code...
}
function formatMoney(value)creates a reusable function that accepts a value parameter.- This function will format any number as currency with a dollar sign and two decimal places.
- We'll break down what each line does in the next sections.
Rounding up with Math.ceil
The first line rounds our value up to the nearest cent:
value = Math.ceil(value * 100) / 100;
value * 100converts dollars to cents (e.g. 15.666 becomes 1566.6).Math.ceil()rounds up to the nearest whole number (1566.6 becomes 1567)./ 100converts back to dollars (1567 becomes 15.67).
For example:
15.666becomes15.6715.671becomes15.6815.60stays15.60
Fixing decimal places with toFixed
The second line ensures we always show exactly two decimal places:
value = value.toFixed(2)
.toFixed(2)converts the number to a string with exactly 2 decimal places.15.6becomes"15.60"15.666becomes"15.67"- This gives us consistent formatting for all currency values.
Note that
toFixed()returns a string, not a number. This is fine since we're displaying the value, not calculating with it.
Adding the dollar sign
The final line adds the currency symbol:
return '$ ' + value;
'$ 'is a string with a dollar sign and a space.+ valueconcatenates (joins) the dollar sign with the formatted number.returnsends this formatted string back to wherever the function was called.
For example, formatMoney(15.666) returns "$ 15.67".
Using the formatMoney function
Now let's use our new function to format all currency displays. Update your update function:
document.getElementById('tipPercent').innerHTML = tipPercent + '%';
document.getElementById('tipValue').innerHTML = formatMoney(tipValue);
document.getElementById('totalWithTip').innerHTML = formatMoney(bill + tipValue);
document.getElementById('splitValue').innerHTML = split;
document.getElementById('billEach').innerHTML = formatMoney(newBillEach);
document.getElementById('tipEach').innerHTML = formatMoney(tipEach);
- We wrap each currency value with
formatMoney(). - The tip percentage doesn't need formatting since it's already a percentage.
- Now all dollar amounts will display consistently with
$ XX.XXformat.
Creating a split formatting function
Let's create another helper function to properly display "1 person" vs "2 people". Add this above your update function:
function formatSplit(value) {
if (value === '1') return value + ' person'
return value + ' people'
}
function formatSplit(value)creates a function to format the split count.if (value === '1')checks if the value is exactly '1' (as a string).return value + ' person'returns "1 person" for singular.return value + ' people'returns the value plus " people" for plural cases.
The value is a string because it comes directly from the range input's
.valueproperty.
Using the formatSplit function
Now update the split value display in your update function:
document.getElementById('splitValue').innerHTML = formatSplit(split);
- This replaces the raw number with properly formatted text.
Testing your formatted output
Open your calculator in the browser and test:
- Enter a bill amount like
100.5 - Move the tip slider to
15% - Adjust the split slider
You should now see:
- All currency values formatted as
$ XX.XX - Split displaying as "1 person" or "X people"
- Calculations rounded up to the nearest cent
Much better!
Your complete code so far
Here's what your JavaScript should look like now:
function formatMoney(value) {
value = Math.ceil(value * 100) / 100
value = value.toFixed(2)
return '$ ' + value
}
function formatSplit(value) {
if (value === '1') return value + ' person'
return value + ' people'
}
function update() {
let bill = Number(document.getElementById('yourBill').value)
let tipPercent = document.getElementById('tipInput').value
let split = document.getElementById('splitInput').value
let tipValue = bill * (tipPercent / 100)
let tipEach = tipValue / split
let newBillEach = (bill + tipValue) / split
document.getElementById('tipPercent').innerHTML = tipPercent + '%'
document.getElementById('tipValue').innerHTML = formatMoney(tipValue)
document.getElementById('totalWithTip').innerHTML = formatMoney(
bill + tipValue
)
document.getElementById('splitValue').innerHTML = formatSplit(split)
document.getElementById('billEach').innerHTML = formatMoney(newBillEach)
document.getElementById('tipEach').innerHTML = formatMoney(tipEach)
}
const container = document.getElementById('container')
container.addEventListener('input', update)
Understanding the limitations
While our formatMoney function works well, it's a simplified approach with some limitations:
- Currency symbol is hardcoded: It always shows
$, which won't work for other currencies. - No locale support: Different countries format currency differently (e.g.
$1,000.00vs1.000,00 $). - Manual rounding logic: We have to handle the rounding ourselves.
For a production application or international audience, there's a better way!
Introducing Intl.NumberFormat
JavaScript includes a built-in API called Intl.NumberFormat that provides professional currency formatting with internationalization support.
Let's create an improved version of our formatMoney function:
function formatMoney(value) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(value)
}
Intl.NumberFormatis a built-in JavaScript object for formatting numbers.'en-US'specifies the locale (United States English formatting rules).style: 'currency'tells it to format as currency.currency: 'USD'specifies US Dollars..format(value)applies the formatting to our value.
How Intl.NumberFormat improves formatting
This approach has several advantages:
- Automatic rounding: No need for
Math.ceiland division by 100. - Proper decimal places: Automatically shows 2 decimal places for USD.
- Correct symbol placement: Follows locale rules for symbol positioning.
- Thousands separators: Automatically adds commas (e.g.
$1,234.56). - International support: Easy to change locale and currency.
For example:
formatMoney(1234.5)returns"$1,234.50"formatMoney(0.666)returns"$0.67"formatMoney(15)returns"$15.00"
Comparing both approaches
Here's a comparison of the two methods:
Simple approach (good for learning):
function formatMoney(value) {
value = Math.ceil(value * 100) / 100
value = value.toFixed(2)
return '$ ' + value
}
Professional approach (better for real projects):
function formatMoney(value) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(value)
}
Both work perfectly fine for our calculator! The first approach is easier to understand when learning, while the second is more powerful and follows best practices.
Using different currencies (optional)
If you want to experiment with Intl.NumberFormat, try changing the currency:
British Pounds:
function formatMoney(value) {
return new Intl.NumberFormat('en-GB', {
style: 'currency',
currency: 'GBP',
}).format(value)
}
Euros:
function formatMoney(value) {
return new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR',
}).format(value)
}
Japanese Yen:
function formatMoney(value) {
return new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY',
}).format(value)
}
Notice how each locale formats currency differently—the API handles all these details automatically!
Final code
Here's the complete HTML with formatted currency and split display:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,700;1,400&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles.css" />
<title>Quick Tip</title>
</head>
<body>
<main id="container">
<h1>Quick Tip</h1>
<section>
<div class="bill">
<label for="yourBill">Bill</label>
<input type="number" placeholder="Your bill" id="yourBill" />
</div>
<div>
<div class="space-between">
<label for="tipInput">Select tip</label
><span id="tipPercent"></span>
</div>
<input type="range" value="0" id="tipInput" class="range" />
</div>
<div class="space-between">
<span>Tip</span>
<span id="tipValue"></span>
</div>
<hr />
<div class="space-between total">
<span>Total</span>
<span id="totalWithTip"></span>
</div>
</section>
<section>
<div>
<div class="space-between">
<label for="splitInput">Split</label>
<span id="splitValue"></span>
</div>
<input
type="range"
min="1"
max="10"
value="1"
id="splitInput"
class="range"
/>
</div>
<div class="space-between">
<span>Bill each</span>
<span id="billEach"></span>
</div>
<div class="space-between">
<span>Tip each</span>
<span id="tipEach"></span>
</div>
</section>
</main>
<script>
function formatMoney(value) {
value = Math.ceil(value * 100) / 100
value = value.toFixed(2)
return '$ ' + value
}
function formatSplit(value) {
if (value === '1') return value + ' person'
return value + ' people'
}
function update() {
let bill = Number(document.getElementById('yourBill').value)
let tipPercent = document.getElementById('tipInput').value
let split = document.getElementById('splitInput').value
let tipValue = bill * (tipPercent / 100)
let tipEach = tipValue / split
let newBillEach = (bill + tipValue) / split
document.getElementById('tipPercent').innerHTML = tipPercent + '%'
document.getElementById('tipValue').innerHTML = formatMoney(tipValue)
document.getElementById('totalWithTip').innerHTML = formatMoney(
bill + tipValue
)
document.getElementById('splitValue').innerHTML = formatSplit(split)
document.getElementById('billEach').innerHTML = formatMoney(newBillEach)
document.getElementById('tipEach').innerHTML = formatMoney(tipEach)
}
const container = document.getElementById('container')
container.addEventListener('input', update)
</script>
</body>
</html>
Summary
In this lesson, you learned how to:
- Create reusable helper functions to format values.
- Use
Math.ceil()to round numbers up to avoid underpayment. - Use
.toFixed()to control decimal places in number formatting. - Concatenate strings to add currency symbols.
- Handle singular and plural text properly with conditional logic.
- Use the
Intl.NumberFormatAPI for professional currency formatting. - Understand the trade-offs between simple and advanced formatting approaches.
- Format currency for different locales and currencies.
Your JavaScript tip calculator is now complete!