Stop reinventing how to render price— UxNow #4

Thibault Friedrich
7 min readApr 16, 2024

A few months ago, I published an article about UX responsibilities for a front-end developer. After looking back, I noticed that one of the topics didn't receive enough attention: how to render prices.

So I went back to work and I investigated deeper the international conventions and how web businesses render prices. I evaluated dozens of large companies from various business sectors like Apple, Airbnb, Air Canada, Amazon, Booking.com, British Airways, Delta Airline, Nike, Walmart, Uber, and Zara.

You can see the results of my investigations there: https://github.com/friedrith/discover-web/blob/master/intl-number-format/docs/examples-prices.md

So I will show you in this article, how you should render your prices. I will explain both the product vision and technical details so if you are a designer or product owner, I suggest you read this article too.

Prices are everywhere

If you develop a new product, you certainly have a price to show somewhere. It may be a pricing section or a product gallery.

We could think that prices are something so basic and banal that all the websites would display the prices in the same format.

Big mistake!

And all websites are concerned. From Airbnb to Nike, passing by Booking.com and Air Canada, nobody follows the same pattern.

UI Designers always try to reinvent how to render prices. Some visuals seem more attractive than others. Product teams, eager to deliver faster, often cut in the features and ask for a good enough version, supporting fewer currencies and locales.

So developers have to implement custom solutions. And it is counter-productive because :

  • it has more bugs
  • it takes more time to implement
  • is not localized enough (yes Spoiler: prices are not displayed the same way in France, Germany, Japan, and USA)
  • it doesn't support multiple currencies

So we will see later that it is a wrong idea since it is often faster to implement a quick and scalable solution using standards.

If you are Airbnb, you may allow yourself spending months to render prices but it is not the case for most of the businesses. So stick to the standard rendering and save yourself some time.

In the rest of the article, I will show you the standards you should follow based on both the international conventions and the practices of international companies.

The price: a combination of 3 variables

Rendering a price seems simple but 3 variables impact the price rendering:

  1. the separator of decimals and the separators of thousands
  2. the number of decimal digits
  3. the currency symbol

Separators

The separators are not specific to prices but on how to render numbers in general. They depend on the locale (the language of a country). For example 1234.56 is displayed:

  • "1,234.56" in the USA
  • "1 234,56" in France
  • "1.234,56" in Germany

It becomes even more tricky when there are multiple languages in a country like Canada or Belgium.

It is important to use the right separator otherwise user may misunderstand the prices in their language. Screen reader may also misread the prices for users requiring more accessibility.

Hopefully, on this topic, everybody seems aligned. All the companies use the same international standards. Each country has its way and you must follow it depending on the user locale (country * language).

You can find the details here: https://en.wikipedia.org/wiki/Decimal_separator

There is a native way to automatically render a number with the right separator based on the locale. We will discover that later.

Number of digits after the decimal separator

You could be inclined to always show 2 decimals but in fact, it depends on the currency. For example, the Japanese currency, the YEN, doesn't have cents so decimals don't make sense for YEN. On the opposite, some currencies must show 3 or even 4 decimals.

The ISO 4217 specifies the number of digits after the decimal separator by country. So for example, a price in US dollars should never be written 12.1 but 12.10 and not 12.157 but 12.16 .

After checking the Web companies, we can find two different logics:

  1. always displaying the decimals even if the number is an integer.
  2. displaying the decimals only if the number is a float

Sometimes a website may use both formats depending on the situation. For example, Apple uses the first format in the payment and shopping sections but uses the second format on the landing pages.

I suggest you to stick to one of these 2 formats too. You can also do like Apple and mix both formats. But always follow the numbers of digits specified by ISO 4217 by currency.

There is a native way to automatically show the right decimals based on the currency. We will see that later too.

Currency symbol

Now the mess arrives. There are so many ways to show the currency symbol. These are a few examples from existing websites:

  • $1,000.00
  • US$1,000.00
  • US$ 1,000.00
  • USD$ 1,000.00
  • $ 1,000.00 USD
  • €1,000.00
  • 1,000.00€
  • 1,000.00 EUR

Not all examples above should be followed however.

The currency symbol is a specific character like $, ¥, €, £.

One extra challenge is that few currencies have the same symbol as the Dollar $. So a currency code was introduced with ISO 4217 to identify currency with a unique 3-letter code like USD or EUR. There is also a short currency code that can be used combined with a symbol like US $.

You can already feel it will give a lot of variants.

Each web company has its way of showing the currency but I could extract a few good practices:

  • Depending on the locale, the currency is displayed at the left or right of the amount
  • There is no need to add the extra US, CA, etc if you display the price in the locale of the currency. For example, if you have a price in US Dollars, you can just use "$" for a user in the USA but you should use "US $" for a user in Canada.
  • You can either use a short currency code+currency symbol (like US$) OR the unique currency code (USD).

With all these specifications you could feel, it would be so hard to follow them all but it is better to keep it simple, and stupid until your business is a multi-billion success.

The solution exists natively in all the browsers!

For product people: you can stop there and just admire the demo I created so you see I don't lie: https://learn.interaction-dynamics.io/examples/price-rendering . If it works for you, remember to choose this way to render prices for your next product. Any other solution will be a waste of time and money.

Technical Solution

Intl.NumberFormat

The magic browser API to use is the Intl.NumberFormat . This function works for multiple number formats including currency. You just need to provide the locale, the currency, and the amount.

const formattedPrice = new Intl.NumberFormat(locale, {
style: 'currency',
currency,
}).format(price)

It works in all the modern browsers:

This API supports all the good practices I listed above:

  • the separators are based on the locale
  • the number of decimals is based on the currency
  • the currency symbol is displayed on the right position
  • the currency symbol is explicit for another country but remains shorter for the currency of the same country. US dollars are "$" in the USA and "US$" in Canada.
  • both the symbol+short currency code OR currency code.

The results look like below ⬇️:

By playing with the options and very low extra code, you can refine and add a few customizations like:

  • no decimal for integer price:
  • currency code instead of currency symbol:
  • a pretty style:

Compatibility

All these examples support all the locales and currencies. And since there is low code, there are fewer bugs too 😉.

To be sure, I wrote tests to check my code in a lot of situations:

As you can see all the tests passed in the continuous integration: https://github.com/friedrith/discover-web/actions/workflows/validate-intl-number-format.yml

Demo

You can find a demo running below. For each situation, there is the code example too:

Conclusion

I hope I proved to you that it is not worth implementing a custom solution and you should use the native API. So as a product owner or a designer, please don't specify crazy formats. And as a developer, please force your team to use this Intl.NumberFormat .

Did you like this article? Remember to clap 😜 !

I am Thibault, a Frontend and UX engineer passionate about UX, Code craftsmanship, productivity, and science fiction and I post new articles every month. If you are interested in these topics, feel free to follow me on Medium: https://medium.com/@thibault-friedrich.

--

--

Thibault Friedrich

Front-end developer, Tech addict, UX lover, Code Crafter, Freelance. I publish high quality articles every month.