<input type="number">
number
类型的 <input>
元素用于让用户输入一个数字,其包括内置验证以拒绝非数字输入。
浏览器可能会选择提供步进箭头,让用户可以使用鼠标增加和减少输入的值,或者只需用指尖敲击即可。
尝试一下
不支持 number
类型的浏览器会回退为标准的 text
输入框。
值 | 表示一个数字的 Number ,或为空 |
事件 | change 和 input |
支持的公共属性 | autocomplete 、list 、placeholder 和 readonly |
IDL 属性 | list 、value 和 valueAsNumber |
DOM 接口 | |
方法 | select() 、stepUp() 和 stepDown() |
值
附加属性
除了 <input>
元素共有的属性外,数字输入还提供以下属性。
list
list 属性的值是位于同一文档中的 <datalist>
元素的 id
。<datalist>
提供了可输入到当前输入框的一个预定义的值列表。列表中任何与 type
不兼容的值都不包括在建议选项中。所提供的值是建议,不是要求:用户可以从这个预定义的列表中选择,或者提供不同的值。
max
min
placeholder
placeholder
属性是一个字符串,可向用户提供有关该字段中需要什么样的信息的简短提示。它应该是说明预期的数据类型的单词或短语,而不是说明性消息。文本中不得包含回车符或换行符。
如果控件的内容具有方向(LTR 或 RTL),但需要以相反的方向显示占位符,则可以使用 Unicode 双向算法来格式化字符,从而覆盖原有占位符的方向;请参见如何针对双向文本使用 Unicode 控制符获取更多信息。
备注:请尽可能避免使用 placeholder
属性,它在语义上没有其他解释表单的方式有用,并且可能会导致额外的问题。参见 <input>
标签以获取更多信息。
readonly
如果该布尔属性存在,意味着用户将不能编辑此字段。然而其 value
值仍然可以直接通过 JavaScript 代码设置 HTMLInputElement
的 value
属性改变。
备注:由于只读字段不可以拥有值,required
不会对指定了 readonly
属性的字段起作用。
step
使用 number 输入框
number
输入类型只能用于可增长的数字,特别是在使用按钮增减值有助于用户体验的时候。number
输入类型对于显示那些不能严格表示数字(可能只是碰巧包含数字)的值(例如邮政编码、信用卡号等)并不合适。对于非数字输入,请考虑使用不同的 input 类型,例如 <input type="tel">
或其他包含 inputmode
属性的 <input>
类型。
<input type="text" inputmode="numeric" pattern="\d*" />
<input type ="number">
元素可以帮助简化构建在表单中输入数字的用户界面和逻辑。当你使用正确的 type
值 number
创建数字输入时,会自动验证你输入的文本是否为数字,而且通常会一同设置一组用于步进数字值的向上向下按钮。
警告:逻辑上,不应该向数字输入框输入数字以外的字符。某些浏览器允许这些不合法字符,另外一些浏览器不允许;请查看 Firefox bug 1398528。
备注:记住,用户可以在幕后修改 HTML,因此网站不得使用简单的客户端验证来实现任何安全目的。你必须在服务器端验证所提供的值,以确保这些值没有任何安全问题。
此外,移动浏览器通过在用户尝试输入值时显示更适合输入数字的特殊键盘,进一步帮助用户体验。
一个简单的 number 输入框
占位符
有时,提供一个如何输入表单数据的上下文提示是非常友好的。尤其当页面所有<input>
元素都没有说明标签时,会非常重要。这就是使用占位符的原因。占位符是一个通常用于说明一个输入框的 value
应该如何输入的提示值,当元素的 value
为 ""
时,该提示将出现在编辑框里面。一旦有数据输入到编辑框中,占位符就会消失;如果该框被清空,占位符将重新出现。
这里,我们有一个占位符为 "Multiple of 10
" 的 number
输入框。请注意在编辑字段内容时占位符是如何消失的,又是如何重现的。
<input type="number" placeholder="Multiple of 10" />
控制步进大小
默认情况下,向上和向下按钮可以将值增加或减小 1。你可以使用 step
属性来更改此步长值。我们上面的例子中的占位符提示我们其值是 10 的倍数,所以设置 step
的值为 10
是合理的:
<input type="number" placeholder="multiple of 10" step="10" />
在这个例子中,你会发现上下箭头每次会将其值增加和减少 10,而不是 1。你仍然可以手动输入一个不是 10 的倍数的数字,但它会被认为是无效的。
指定最小和最大值
允许小数值
数字输入的一个问题是,步长默认为 1——如果你尝试输入带小数的数字(例如“1.0”),则它将被视为无效。如果要输入一个需要小数的值,则需要修改 step
值(例如,step="0.01"
以允许 2 位小数)。这里有一个简单的例子:
<input type="number" placeholder="1.0" step="0.01" min="0" max="10" />
你可以看到这个例子允许 0.0
到 10.0
之间的任何值,小数点为 2 位。本例中,“9.52”是有效的,但“9.521”无效。
控制输入框大小
提供建议值
你可以通过指定 list
属性来提供一个默认选项列表,用户可以从中选择,该属性包含一个 <datalist>
的 ID 作为其值,而该 ID 又包含一个 <option>
元素的每个建议值;每个 option
的 value
就是数字输入框的相应建议值。
<input id="ticketNum" type="number" name="ticketNum" list="defaultNumbers" />
<span class="validity"></span>
<datalist id="defaultNumbers">
<option value="10045678"></option>
<option value="103421"></option>
<option value="11111111"></option>
<option value="12345678"></option>
<option value="12999922"></option>
</datalist>
验证
我们已经提及了一些数字输入的验证特性,来做个回忆:
<input type="number">
元素自动拒绝任何非数字输入(如果指定了required
,也会拒绝空的输入)。- 你可以使用
required
属性来使得空的输入无效,也就是说,该输入框必须有值填入。 - 你可以使用
step
属性来将有效值限制在一系列步进值中(如 10 的倍数)。 - 你可以使用
min
和max
属性来限制输入的最大与最小值。
以下示例展示了上面所述的所有特性,也使用了 CSS 来根据 input
的不同值,显示合法及不合法的图标:
<form>
<div>
<label for="balloons">要购买气球的数量(10 的倍数):</label>
<input
id="balloons"
type="number"
name="balloons"
step="10"
min="0"
max="100"
required />
<span class="validity"></span>
</div>
<div>
<input type="submit" />
</div>
</form>
请尝试以非法的值提交该表单,如空值、小于 0 或大于 100 的值、不是 10 的倍数的值、或非数字值——来观察一下浏览器如何提示这些错误信息。
该示例应用的 CSS 如下所示:
div {
margin-bottom: 10px;
}
input:invalid + span::after {
content: "✖";
padding-left: 5px;
}
input:valid + span::after {
content: "✓";
padding-left: 5px;
}
我们使用了 :invalid
和 :valid
伪类,在相邻的 <span>
元素上显示一个适当的无效或有效图标作为生成内容,作为有效性的视觉指标。
我们把它放在一个单独的 <span>
元素上,以增加灵活性;一些浏览器在某些类型的表单输入上不能很有效地显示生成的内容(请阅读 <input type="date">
验证一节的示例以了解)。
警告:客户端表单验证不能替代服务端验证。对于某人来说,对 HTML 进行调整以使其绕过验证或完全删除验证太容易了,甚至也可以完全绕开 HTML 并将数据直接提交到服务器。如果服务器端代码无法验证其接收到的数据,则在提交格式不正确的(或太大,类型错误……)的数据时,灾难可能会发生。
模式验证
示例
我们已经介绍过,默认情况下,增量是 1
,你可以使用 step
属性来允许小数输入。
在下面的例子中,我们设置了一个用于输入用户身高的表单;它默认接受以米为单位的身高,但你可以点击相关按钮来改变表单,使其接受英尺和英寸。输入米的身高可以接受小数点后两位。
HTML 代码看起来像这样:
<form>
<div class="metersInputGroup">
<label for="meters">Enter your height — meters:</label>
<input
id="meters"
type="number"
name="meters"
step="0.01"
min="0"
placeholder="e.g. 1.78"
required />
<span class="validity"></span>
</div>
<div class="feetInputGroup" style="display: none;">
<span>Enter your height — </span>
<label for="feet">feet:</label>
<input id="feet" type="number" name="feet" min="0" step="1" />
<span class="validity"></span>
<label for="inches">inches:</label>
<input id="inches" type="number" name="inches" min="0" max="11" step="1" />
<span class="validity"></span>
</div>
<div>
<input
type="button"
class="meters"
value="Enter height in feet and inches" />
</div>
<div>
<input type="submit" value="Submit form" />
</div>
</form>
你会看到,我们正在使用许多我们已经在前面的文章中看过的属性。由于我们想接受以厘米为单位的米值,我们将 step
值设置为 0.01
,这样像 1.78 这样的值就不会被视为无效。我们还为这个输入提供了一个占位符。
我们使用 style="display: none;"
隐藏了英尺和英寸的输入,所以米是默认的输入类型。
现在来看看 CSS 代码——跟之前的验证部分样式看起来是一样的,没什么可说的:
div {
margin-bottom: 10px;
position: relative;
}
input[type="number"] {
width: 100px;
}
input + span {
padding-right: 30px;
}
input:invalid + span::after {
position: absolute;
content: "✖";
padding-left: 5px;
}
input:valid + span::after {
position: absolute;
content: "✓";
padding-left: 5px;
}
最后是一些 JavaScript 代码:
const metersInputGroup = document.querySelector(".metersInputGroup");
const feetInputGroup = document.querySelector(".feetInputGroup");
const metersInput = document.querySelector("#meters");
const feetInput = document.querySelector("#feet");
const inchesInput = document.querySelector("#inches");
const switchBtn = document.querySelector('input[type="button"]');
switchBtn.addEventListener("click", () => {
if (switchBtn.getAttribute("class") === "meters") {
switchBtn.setAttribute("class", "feet");
switchBtn.value = "Enter height in meters";
metersInputGroup.style.display = "none";
feetInputGroup.style.display = "block";
feetInput.setAttribute("required", "");
inchesInput.setAttribute("required", "");
metersInput.removeAttribute("required");
metersInput.value = "";
} else {
switchBtn.setAttribute("class", "meters");
switchBtn.value = "Enter height in feet and inches";
metersInputGroup.style.display = "block";
feetInputGroup.style.display = "none";
feetInput.removeAttribute("required");
inchesInput.removeAttribute("required");
metersInput.setAttribute("required", "");
feetInput.value = "";
inchesInput.value = "";
}
});
在声明了一些变量之后,我们为按钮添加一个事件监听器来控制切换机制。这很简单,主要是改变按钮的类别和标签,并在按钮被按下时更新两组输入的显示值。请注意,我们不是在米和英尺/英寸之间来回转换,现实生活中的网络应用可能会这么做。
备注:请注意,当用户点击按钮时,我们从隐藏的输入中移除 required
属性,并清空 value
属性。这样我们就可以在两个输入组都没有填写的情况下提交表单,而不会提交那些我们不想提交的数据。如果我们不这样做,你就必须同时填入英尺/英寸和米来提交表单了!
无障碍
<input type="number">
元素的隐含 role 是 spinbutton
。如果 spinbutton 对你的表单控件来说不是一个重要的功能,那就不要使用 type="number"
;此时,请使用带有 pattern
属性的 inputmode="numeric"
,将字符限制在数字和相关字符。如果坚持使用 <input type="number">
,用户在试图做其他事情时,有可能意外地增加一个数字。此外,如果用户试图输入不是数字的东西,也没有明确的反馈说明他们做错了什么。
也可以考虑使用 autocomplete
属性,帮助用户更快完成表单,减少出错的机会。例如,要在一个邮编字段上启用自动填写功能,请设置 autocomplete="postal-code"
。
规范
Specification |
---|
HTML Standard # number-state-(type=number) |
浏览器兼容性
BCD tables only load in the browser