You want to use <input type="number">
fields in your applications.
However, your desktop users may encounter some weird quirks:
- 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).
- 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.
- 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.
- 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.
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.
Posted by Arne Hartherz to makandra dev (2021-10-11 08:29)