Better numeric inputs in desktop browsers

Using an <input type="number"> for numeric inputs is incredibly nice for your mobile users, because their browsers show numeric keyboards.
However, your desktop users will encounter some weird quirks:

  1. Aside from allowing only digits and decimal separators, an "e" is also allowed (to allow scientific notation like "1e3").
    • Non-technical users will be confused by this.
    • Your server needs to understand that syntax. If it converts only digits (e.g. to_i in Ruby) you'll end up with wrong values (like 1 or 13).
  2. Users can change values with up and down arrow keys.
    • This can be useful, if users know about it.
    • To most users, this is often unexpected (text inputs look alike and move the cursor to start/end) and they will rather change values accidentally than on purpose.
  3. Some browsers (at least Firefox) will change values when you scroll the mouse wheel while your mouse pointer hovers the (focused) input.
    • This is terrible. Nobody wants that.
    • Users will change values by accident.
  4. Some browsers (at least Firefox) still allow regular letters for numeric inputs.
    • Users might enter values like "20€".
    • Firefox parses that as an empty input value, leading to validation errors and thus user confusion.
  5. The decimal separator depends on the OS (maybe Browser) locale.
    • For example, users with a German locale setting are allowed to also use a Comma as a decimal separator, i.e. "1,23" works just like "1.23", while users with other locales may only be allowed to use "1.23".
    • This might break your integration tests if you can't control the Browser's locale setting.
    • As a plus, browsers will always send values with point as decimal separator. Your server does not need to do any "German values parsing".

We can not fix/change the last quirk, but all others.

Here is how. We've wrapped the code with an Unpoly compiler Archive , but you can wrap it however you like.

up.compiler('input[type="number"]', (element) => {

  // Number inputs allow incrementing/decrementing with arrow keys, and support exponential notation
  // (in some browsers even regular letters). We want neither.
  element.addEventListener('keydown', (event) => {
    const key = event.key
    if (key === 'ArrowUp' || key === 'ArrowDown' || key.length === 1 && !event.ctrlKey && !event.altKey && !key.match(/[0-9\-+,.]/)) {
      event.preventDefault()
    }
  })

  // Some browser (at least Firefox) will increment/decrement a number when using the mouse's scroll wheel
  // above a focused number input. Since this can lead to users changing values by accident, we want to avoid that.
  element.addEventListener('wheel', (event) => {
    if (element.matches(':focus')) {
      event.preventDefault()
    }
  })
  
})

Example:

Arne Hartherz about 1 month ago
This website uses short-lived cookies to improve usability.
Accept or learn more