Read more

Better numeric inputs in desktop browsers

Arne Hartherz
October 11, 2021Software engineer at makandra GmbH

You want to use <input type="number"> fields in your applications.
However, your desktop users may 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 instead of 1000).
  2. Users can change values with the 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 when trying to scroll the page.
  4. Some browsers (at least Firefox) still allow regular letters for numeric inputs (as if specifying inputmode="numeric").
    • Users might enter values like "20€".
    • Firefox parses that as an empty input value, leading to validation errors and thus user confusion.
Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

We can fix all that with JavaScript:

const element = document.querySelector('#your-input')

// 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
  const nonNumberKey = key.length === 1 && !event.ctrlKey && !event.altKey && !key.match(/[0-9\-+,.]/)
  if (key === 'ArrowUp' || key === 'ArrowDown' || nonNumberKey) {
    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()
  }
})

You can easily wrap this code your favorite frontend framework.

Additionally, you can hide the number field's up/down arrow buttons with CSS:

input[type="number"] {
  -moz-appearance: textfield;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
}

See https://codepen.io/foobear/pen/dyzyBBX Show archive.org snapshot for a demo page.

Arne Hartherz
October 11, 2021Software engineer at makandra GmbH
Posted by Arne Hartherz to makandra dev (2021-10-11 10:29)