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 UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
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)