Solving Cross-Browsers Localization on Numeric Inputs

1234.56 vs 1234,56

While working at Takeaway.com developing a multilingual, multi-currency, multi-whatever-you-want app we released our first version to be used in a local restaurant in the Netherlands.

A couple of days later our product-owner from the Netherlands contacted our product-manager in Israel and told him that he used the catalog feature on our app and couldn’t enter the comma (,) character in the price field.

Duh!
The decimal separator is a dot (.), not a comma, well, at least I thought so.

My journey to numbers-localization and cross-browsers support begins.

The problem(s):

Browsers define localization differently.

“Localization is the process of adapting internationalized software for a specific region or language by translating text and adding locale-specific components”

Input[“number”] shadow-dom

Each browser adds a shadow-dom element to the input and displays the text, then, it manipulates the value and saves it under “valueAsNumer” and “value” properties.

Input element properties

If we enter “1.” for example, the browser will update the shadow-dom element with “1.” but will not update the “value/valueAsNumber” properties until we don't add another digit.

Input “value” property and shadow-dom element value are different

How the browser defines the locale?

  • Chrome - by the browser’s language.
  • Firefox - by the “lang” attribute.
<input type=”number” step="0.01" lang="nl"/>

Our product-owner used Chrome set to English so his locale was EN and not NL, so he couldn’t enter a comma as a decimal separator.

But there are more differences between the browsers:

Chrome
Firefox
  • Visual differences: Height of the input, border-radius, visibility of the increase/decrease arrows, different focus design.
  • Behavior differences: In Chrome, you can’t enter non-numeric characters but in FF you can. In Chrome the validation happens after the form submission, but in FF is immediate.

The visual differences can be easily solved using CSS-reset.

The behavior differences are more complicated:

  • Why can I enter a dot but can’t enter a comma?
  • Why can I enter the minus sign wherever I want in the number?
  • Why do I need to specify the “step” attribute to enter a decimal value?

Maybe using the “type” attribute is not a good idea…

What about mobile browsers?

Mobile browsers are a whole different story because we don’t have a physical keyboard but only an on-screen keyboard — what is the difference, you ask?
Every key in our physical keyboard is mapped to a key-code, the numbers 0–9 mapped to key-codes 48–57 respectively, Latin letters are 65–90, etc…

Knowing that we can check whether the value is a numeric value, including special characters as the minus sign or decimal separator, and restrict everything else, right? NOPE! In mobile keyboards, all of the keys are mapped to 0 or 8 or some other values (depends on the keyboard) so what can we do?

Keyboards layouts to the rescue!
Every keyboard can have a different layout depending on its purpose:
Entering a phone number, a date or a URL are just some examples of different layouts that make our experience better.

Adding the “inputmode” attribute

<input step="0.01" inputmode="decimal"/>

will open a numeric keyboard with the decimal separator — so the user can’t enter non-numeric characters.

Android & IOS — decimal keyboards

The solution:

  • Provide a unified solution for localization.
  • Allow decimals, negatives, action keys, and numeric values.
  • Restrict every non-numeric character.
  • Preserve the native HTML input validation.
  • Support numeric layout for mobile.

Am I as a web-developer need to take all of these things into consideration every time I write a numeric-input field?
Well, yes, but I can make your life a little bit easier with my
custom numeric-input directive:

The solution is vanilla, but the library is built with Angular.

PRs and feature requests are welcome!

Thank you for reading my first article!
Hope you liked it!
Feel free to leave feedback or questions in the comments.

Written by

Front-end developer, Angular enthusiast

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store