使用 `inputmode`实现手指友好的数字输入

Avatar of Ollie Williams
Ollie Williams 发布

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200美元免费额度!

表单在移动设备上常常让人头疼。 我们可以通过对上下文做出反应,尽可能地使流程变得流畅。 期待数字值的输入字段应该具有数字UI。 在小屏幕上调出数字键盘在大多数平台上都很容易——只需使用<input type="number">

A screenshot of the iOS number keyboard with keys for numbers one through ten.

这个大按钮数字键盘对手指友好,有助于防止用户因沮丧而放弃您的表单。 但是,type="number"并不适用于所有数字

在(大多数)较大的屏幕上,数字输入带有增量/减量按钮。 这是我们默认情况下免费获得的一个有用的UI元素。 但是,它确实使这种类型的输入对于信用卡号等完全不合适

A default number input that displays the up and down arrows that allow users to increase and decrease numbers in the field.
数字输入的默认UI在所有桌面浏览器中看起来都类似于这样

规范本身就明确说明了这一点。

type=number状态不适用于碰巧仅由数字组成但严格来说不是数字的输入。 例如,它不适用于信用卡号或美国邮政编码。 确定是否使用type=number的一种简单方法是考虑输入控件是否有意义地使用微调框界面(例如,带有“向上”和“向下”箭头)。 信用卡号的最后一位数字出错1位并非小错,它与所有数字都错误一样严重。 因此,用户不应使用“向上”和“向下”按钮来选择信用卡号。 当微调框界面不合适时,type=text可能是正确的选择(可能带有pattern属性)。

使用CSS隐藏向上和向下按钮很容易

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

需要注意的是,这并不是数字输入和文本输入之间唯一的区别您绝对应该遵循此方面的规范! 一些旧版浏览器会为数字输入删除前导零,这对美国邮政编码来说将是一个大问题。 通常有用的maxlength属性在数字输入上被忽略

为什么有人会不喜欢这样一个有用的输入?

答案归结为验证和将输入用于错误的事情。数字输入默认执行输入清理。 如果用户输入任何不是有效数字的内容,该值将等于空字符串——无论用户在屏幕上看到什么。

这种输入清理可能会让开发者感到困惑,而且无法关闭。 如果您希望允许输入不是有效数字的内容,请勿使用type="number"

A screenshot showing a number input that is filled with numbers and includes dashes between some of the numbers.
Chrome中的数字输入。 这可能是您用例中的有效输入,但在数字输入看来是非法的。
var numberinput = document.querySelector('input[type="number"]')
numberinput.value // will be ""

这可能不是您直觉上期望的结果。 但是,如果您遵循规范,并且仅将数字输入用于其设计目的——实际数字——此行为则不会有问题。

数字输入替代方案

iOS解决方案:在文本输入上使用`pattern`属性

在iOS设备上,使用值为[0-9]*pattern属性将调出数字键盘。 这仅适用于此确切的模式——您不能允许任何额外的字符。

<label for="creditcard">credit card number:</label> <input pattern="[0-9]*" type="text" name="creditcard">
The iOS number keyboard that displays only numbers one through ten and no other special characters.
带有pattern属性的iOS

请记住,当显示此键盘时,iPhone不会允许用户切换键盘类型。确保这些是他们正确填写输入所需的唯一键

如果要在iOS上调出大型数字键的键盘,则需要在数字输入上使用pattern属性。 否则,您将获得小巧且对手指友好的按钮

A screenshot of the iOS keyboard displaying both numbers and letters.
<input type="number">的iOS键盘

更好的解决方案:`inputmode`

inputmode已经成为WHATWG规范几年了,并且从Chrome 66版本开始最终得到了实现

此浏览器支持数据来自Caniuse,其中包含更多详细信息。 数字表示浏览器在该版本及更高版本中支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
669579

移动/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712712.2-12.5

为了获得尽可能广泛的支持,可以将其与pattern属性结合使用以用于iOS

<label for="creditcard">credit card number:</label> <input inputmode="numeric" pattern="[0-9]*" type="text" name="creditcard">

这使开发人员能够完全控制移动UI,而没有任何额外负担。 它使UI对手指友好,同时又比pattern属性更通用,因为我们可以允许任何我们喜欢的字符。 它控制一件事情——并且只有一件事。 inputmode是当使用type="number"不合适时的一个很好的解决方案。

有些人会更进一步,一旦inputmode获得更好的支持,就会完全放弃type="number"。 我不确定这是否明智,但type="number"可能会存在问题。

if (numberInput.validity.valueMissing) {
errorMessage.textContent = "field must not be empty"
}
A screenshot of a number input filled with numbers and special characters with an error message below it that informs the user the field is empty.
与人眼相反,该字段为空…

如果您想明确警告空数字输入,则需要使用

if (numberInput.validity.valueMissing && !numberInput.validity.badInput) {
errorMessage.textContent = "field must not be empty"
}

根据Google的说法,与台式机相比,用户在移动设备上放弃购买的频率是其两倍。 手机上的销售额仅占所有完成的在线购买的三分之一。 显然,人们无法容忍笨拙地浏览设计糟糕的表单并在微小的输入上戳戳点点。 数据输入需要毫不费力。 虽然浏览器支持目前较低,但我们实际上只是在等待移动浏览器。 桌面支持在很大程度上无关紧要。 HTML5引入的输入元素很棒,但它们错过了一些极端情况。 这可以填补一些空白。