HTML 输入元素是 Web 表单的基础。HTML 拥有超过 20 种输入类型和数十个属性,正确理解和使用它们对于构建无障碍、用户友好且移动端优化的表单至关重要。本HTML 输入类型与属性完整指南涵盖所有输入类型、验证属性、无障碍最佳实践和移动端优化技巧。
1. 文本输入类型
基于文本的输入是最常见的表单元素。HTML5 引入了多种专用文本类型,提供内置验证并触发适当的移动端键盘。
基础文本输入
text 类型是默认且最通用的输入。它接受任何字符串值,适用于姓名、地址和一般自由文本。
<!-- Basic text input -->
<label for="username">Username:</label>
<input type="text" id="username" name="username"
placeholder="Enter your username"
maxlength="30" required>
<!-- With pattern validation -->
<label for="zipcode">ZIP Code:</label>
<input type="text" id="zipcode" name="zipcode"
pattern="[0-9]{5}" title="5-digit ZIP code"
placeholder="12345">密码输入
password 类型用点或星号掩盖用户输入。浏览器可能会提供保存密码并在后续访问时自动填充。
<label for="password">Password:</label>
<input type="password" id="password" name="password"
minlength="8" maxlength="128" required
autocomplete="new-password"
aria-describedby="pwd-help">
<small id="pwd-help">Minimum 8 characters</small>电子邮件输入
email 类型提供内置的电子邮件格式验证。在移动设备上,它会触发带有 @ 符号的键盘。
<label for="email">Email:</label>
<input type="email" id="email" name="email"
placeholder="user@example.com" required
autocomplete="email">
<!-- Allow multiple emails (comma-separated) -->
<input type="email" id="emails" name="emails" multiple>电话输入
tel 类型不强制任何特定格式(各国电话号码格式不同),但在移动设备上会触发数字电话键盘。
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone"
pattern="[+]?[0-9]{1,4}[\s-]?[0-9]{6,14}"
placeholder="+1 555-123-4567"
autocomplete="tel">URL 输入
url 类型验证输入是否包含有效的 URL 格式。在移动端,它通常显示带有 / 和 .com 按键的键盘。
<label for="website">Website:</label>
<input type="url" id="website" name="website"
placeholder="https://example.com"
autocomplete="url">搜索输入
search 类型的行为类似文本输入,但浏览器可能会以不同方式呈现(如带有清除按钮),并与 search ARIA 角色配合使用。
<label for="search">Search:</label>
<input type="search" id="search" name="q"
placeholder="Search articles..."
aria-label="Search articles">2. 数字与范围输入
数字输入将用户输入限制为数字并提供微调器控件。range 类型提供滑块界面,用于在定义范围内选择值。
数字输入
number 类型显示用于递增/递减的微调箭头。使用 min、max 和 step 属性来控制允许的范围和步进值。
<!-- Basic number input -->
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity"
min="1" max="100" step="1" value="1">
<!-- Decimal number (e.g., price) -->
<label for="price">Price:</label>
<input type="number" id="price" name="price"
min="0" max="99999.99" step="0.01"
placeholder="0.00">范围输入(滑块)
range 类型渲染为滑块控件。与 number 不同,它默认不显示确切值 — 你需要使用 JavaScript 或 <output> 元素来显示它。
<!-- Range slider with output display -->
<label for="volume">Volume:</label>
<input type="range" id="volume" name="volume"
min="0" max="100" step="5" value="50"
oninput="this.nextElementSibling.value = this.value">
<output>50</output>
<!-- Range with list of tick marks -->
<input type="range" min="0" max="100" step="25" list="marks">
<datalist id="marks">
<option value="0" label="0%"></option>
<option value="25" label="25%"></option>
<option value="50" label="50%"></option>
<option value="75" label="75%"></option>
<option value="100" label="100%"></option>
</datalist>3. 日期与时间输入
HTML5 日期和时间输入提供原生日期选择器,无需 JavaScript 库。现代浏览器的支持已经非常好。
日期输入
date 类型呈现日期选择器界面。无论显示格式如何,值始终格式化为 YYYY-MM-DD。
<label for="birthday">Birthday:</label>
<input type="date" id="birthday" name="birthday"
min="1900-01-01" max="2025-12-31"
value="2000-01-15">时间输入
time 类型允许选择一天中的时间。值为 24 小时制 HH:MM 格式,但显示可能根据语言环境显示 AM/PM。
<label for="meeting">Meeting Time:</label>
<input type="time" id="meeting" name="meeting"
min="09:00" max="18:00" step="900"
value="14:30">
<!-- step="900" = 15-minute increments (900 seconds) -->日期时间本地输入
datetime-local 类型将日期和时间选择合并到单个输入中。注意:已弃用的 datetime 类型不应再使用。
<label for="appointment">Appointment:</label>
<input type="datetime-local" id="appointment"
name="appointment"
min="2025-01-01T08:00"
max="2025-12-31T18:00">月份输入
month 类型允许选择年份和月份的组合。适用于信用卡有效期或月度报告。
<label for="card-exp">Card Expiry:</label>
<input type="month" id="card-exp" name="card-exp"
min="2025-01" max="2035-12">周输入
week 类型允许选择一年中的特定周。值格式为 YYYY-Wnn(如 2025-W03)。
<label for="week">Select Week:</label>
<input type="week" id="week" name="week"
min="2025-W01" max="2025-W52">4. 选择输入
选择输入让用户从预定义选项中进行选择。包括复选框、单选按钮、下拉选择和现代 datalist 元素。
复选框
复选框允许用户从一组选项中选择零个或多个。每个复选框独立操作。使用 checked 属性设置默认选中。
<fieldset>
<legend>Interests:</legend>
<label>
<input type="checkbox" name="interests" value="coding" checked>
Coding
</label>
<label>
<input type="checkbox" name="interests" value="design">
Design
</label>
<label>
<input type="checkbox" name="interests" value="devops">
DevOps
</label>
</fieldset>
<!-- Single checkbox for boolean (e.g., terms) -->
<label>
<input type="checkbox" name="terms" required>
I agree to the Terms of Service
</label>单选按钮
单选按钮让用户从一组中选择恰好一个选项。同一组中的所有单选按钮必须共享相同的 name 属性。
<fieldset>
<legend>Payment Method:</legend>
<label>
<input type="radio" name="payment" value="credit" checked>
Credit Card
</label>
<label>
<input type="radio" name="payment" value="paypal">
PayPal
</label>
<label>
<input type="radio" name="payment" value="bank">
Bank Transfer
</label>
</fieldset>下拉选择
<select> 元素创建下拉菜单。虽然不是 <input>,但它是表单选择的重要元素。使用 multiple 实现多选。
<!-- Single select -->
<label for="country">Country:</label>
<select id="country" name="country" required>
<option value="">-- Select --</option>
<optgroup label="North America">
<option value="us">United States</option>
<option value="ca">Canada</option>
</optgroup>
<optgroup label="Europe">
<option value="uk">United Kingdom</option>
<option value="de">Germany</option>
</optgroup>
</select>
<!-- Multi-select -->
<label for="skills">Skills (hold Ctrl to select multiple):</label>
<select id="skills" name="skills" multiple size="5">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="ts">TypeScript</option>
<option value="react">React</option>
</select>数据列表(自动补全)
<datalist> 元素为 <input> 提供自动补全建议。用户可以自由输入或从建议中选择。
<label for="browser">Browser:</label>
<input type="text" id="browser" name="browser"
list="browsers" placeholder="Start typing...">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
</datalist>5. 文件与媒体输入
文件输入允许用户从设备上传文件。hidden 和 image 类型在表单处理中有特殊用途。
文件上传
file 类型打开文件选择对话框。使用 accept 限制文件类型,使用 multiple 允许多文件选择。
<!-- Single file upload -->
<label for="avatar">Upload Avatar:</label>
<input type="file" id="avatar" name="avatar"
accept="image/png, image/jpeg, image/webp">
<!-- Multiple files -->
<label for="documents">Upload Documents:</label>
<input type="file" id="documents" name="documents"
accept=".pdf,.doc,.docx" multiple>
<!-- Any image -->
<input type="file" accept="image/*" capture="environment">
<!-- capture="environment" opens rear camera on mobile -->
<!-- capture="user" opens front camera -->图片提交按钮
image 类型创建图形提交按钮。点击时,表单连同点击位置的 x/y 坐标一起提交。
<!-- Image as submit button -->
<input type="image" src="/img/submit-btn.png"
alt="Submit Form" width="100" height="40">
<!-- Submits: x=123&y=45 (click coordinates) -->隐藏输入
hidden 类型存储随表单提交但对用户不可见的数据。常用于 CSRF 令牌、ID 和跟踪数据。
<!-- CSRF token -->
<input type="hidden" name="_csrf" value="abc123token">
<!-- Record ID for update forms -->
<input type="hidden" name="userId" value="42">
<!-- Tracking / analytics -->
<input type="hidden" name="referrer" value="google">6. 按钮类型
理解按钮类型之间的区别对于正确的表单行为至关重要。使用错误的类型可能导致意外的表单提交。
提交按钮
submit 类型触发表单提交。这是表单内 <button> 元素的默认行为。
<!-- Using <input> -->
<input type="submit" value="Submit Form">
<!-- Using <button> (preferred - allows HTML content) -->
<button type="submit">
Submit Form
</button>
<!-- Submit to a different URL -->
<button type="submit" formaction="/api/draft" formmethod="post">
Save as Draft
</button>重置按钮
reset 类型将所有表单控件恢复为初始值。谨慎使用 — 用户很少需要此功能,且可能误点。
<input type="reset" value="Reset Form">
<!-- or -->
<button type="reset">Clear All Fields</button>普通按钮
button 类型没有默认行为。用于不应提交或重置表单的 JavaScript 驱动操作。
<!-- IMPORTANT: Always set type="button" for non-submit buttons -->
<button type="button" onclick="togglePreview()">
Toggle Preview
</button>
<!-- Without type="button", this defaults to submit inside a form! -->
<button type="button" id="add-row">Add Row</button>7. 验证属性
HTML5 提供强大的内置验证,减少了对 JavaScript 的依赖。这些属性与约束验证 API 配合,提供即时反馈。
required
required 属性在字段为空时阻止表单提交。它适用于 text、email、password、file、checkbox、radio、select 等。
<input type="text" name="fullname" required>
<input type="email" name="email" required>
<input type="checkbox" name="agree" required>
<!-- Style required fields with CSS -->
<style>
input:required { border-left: 3px solid #e74c3c; }
input:valid { border-left: 3px solid #2ecc71; }
</style>pattern
pattern 属性指定输入值必须匹配的正则表达式。始终提供 title 属性来解释预期格式。
<!-- US phone number -->
<input type="tel" name="phone"
pattern="\(\d{3}\) \d{3}-\d{4}"
title="Format: (123) 456-7890">
<!-- Username: letters, numbers, underscores, 3-16 chars -->
<input type="text" name="username"
pattern="[a-zA-Z0-9_]{3,16}"
title="3-16 characters: letters, numbers, underscores">
<!-- Strong password pattern -->
<input type="password" name="password"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="At least 8 chars with uppercase, lowercase, and number">minlength 与 maxlength
这些属性限制用户可以输入的字符数。maxlength 物理上阻止超出限制的输入;minlength 在提交时触发验证。
<!-- Bio: 10 to 500 characters -->
<textarea name="bio" minlength="10" maxlength="500"
rows="4" required></textarea>
<!-- Tweet-like character limit -->
<input type="text" name="status" maxlength="280"
placeholder="What's happening?">min 与 max
min 和 max 属性为数字和日期输入设置边界。超出此范围的值将验证失败。
<!-- Age: 18 to 120 -->
<input type="number" name="age" min="18" max="120">
<!-- Date range -->
<input type="date" name="start"
min="2025-01-01" max="2025-12-31">
<!-- Price: $0.01 to $9999.99 -->
<input type="number" name="price"
min="0.01" max="9999.99" step="0.01">8. 样式与用户体验属性
这些属性通过提供提示、控制自动填充行为和引导焦点来增强用户体验。
placeholder
placeholder 属性在输入框内显示提示文本。当用户开始输入时提示消失。永远不要用 placeholder 替代 label — 它不具备无障碍性且输入时会消失。
<!-- Good: Label + placeholder as hint -->
<label for="email">Email Address</label>
<input type="email" id="email" placeholder="user@example.com">
<!-- Bad: Placeholder as only label (not accessible!) -->
<input type="email" placeholder="Email Address">
<!-- Style placeholder text with CSS -->
<style>
::placeholder {
color: #999;
font-style: italic;
}
</style>autofocus
autofocus 属性在页面加载时自动聚焦输入框。每页只应有一个元素具有此属性。谨慎使用,因为它可能会让屏幕阅读器用户感到困惑。
<!-- Focus the search box on page load -->
<input type="search" name="q" autofocus
placeholder="Search...">autocomplete
autocomplete 属性提示浏览器期望的数据类型,启用智能自动填充。值包括 name、email、tel、address-line1、cc-number 等。
<!-- Full autocomplete for address form -->
<input type="text" name="name" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="address" autocomplete="address-line1">
<input type="text" name="city" autocomplete="address-level2">
<input type="text" name="state" autocomplete="address-level1">
<input type="text" name="zip" autocomplete="postal-code">
<input type="text" name="country" autocomplete="country-name">
<!-- Credit card fields -->
<input type="text" name="cc-name" autocomplete="cc-name">
<input type="text" name="cc-number" autocomplete="cc-number"
inputmode="numeric">
<input type="text" name="cc-exp" autocomplete="cc-exp">
<input type="text" name="cc-csc" autocomplete="cc-csc"
inputmode="numeric">
<!-- Disable autocomplete for sensitive fields -->
<input type="text" name="otp" autocomplete="off">inputmode
inputmode 属性控制移动设备上显示的虚拟键盘,而不改变输入类型或验证行为。
<!-- inputmode values and their keyboards -->
<input inputmode="text"> <!-- Default keyboard -->
<input inputmode="numeric"> <!-- 0-9 only -->
<input inputmode="decimal"> <!-- 0-9 + decimal point -->
<input inputmode="tel"> <!-- Telephone keypad -->
<input inputmode="email"> <!-- @ and . visible -->
<input inputmode="url"> <!-- / and .com visible -->
<input inputmode="search"> <!-- Search/Go button -->
<input inputmode="none"> <!-- No keyboard -->9. 无障碍最佳实践
无障碍表单确保所有用户(包括使用屏幕阅读器和辅助技术的用户)都能与你的输入框交互。无障碍性不是可选的 — 在许多司法管辖区它是法律要求。
标签
每个输入框都必须有关联的 <label>。使用 for 属性匹配输入框的 id,或将输入框包裹在 label 元素内。
<!-- Method 1: Explicit label with for/id -->
<label for="fname">First Name:</label>
<input type="text" id="fname" name="fname">
<!-- Method 2: Implicit label (wrapping) -->
<label>
Last Name:
<input type="text" name="lname">
</label>
<!-- WRONG: No label association -->
<span>Email:</span>
<input type="email" name="email">
<!-- Screen readers cannot identify what this field is for -->ARIA 属性
ARIA 属性为辅助技术提供额外上下文。使用 aria-describedby 提供帮助文本,aria-invalid 标记错误状态,aria-required 作为原生 required 属性的补充。
<!-- Help text with aria-describedby -->
<label for="pwd">Password:</label>
<input type="password" id="pwd" name="pwd"
aria-describedby="pwd-requirements" required>
<div id="pwd-requirements">
Must contain at least 8 characters, one uppercase,
one lowercase, and one number.
</div>
<!-- Error state with aria-invalid -->
<label for="email">Email:</label>
<input type="email" id="email" name="email"
aria-invalid="true"
aria-describedby="email-error">
<div id="email-error" role="alert">
Please enter a valid email address.
</div>
<!-- aria-required for assistive tech -->
<input type="text" name="company"
aria-required="true" required>Fieldset 与 Legend
使用 <fieldset> 分组相关输入,并用 <legend> 提供组标签。这对单选按钮和复选框组尤其重要。
<fieldset>
<legend>Shipping Address</legend>
<label for="street">Street:</label>
<input type="text" id="street" name="street">
<label for="city">City:</label>
<input type="text" id="city" name="city">
</fieldset>
<fieldset>
<legend>Preferred Contact Method</legend>
<label>
<input type="radio" name="contact" value="email"> Email
</label>
<label>
<input type="radio" name="contact" value="phone"> Phone
</label>
<label>
<input type="radio" name="contact" value="sms"> SMS
</label>
</fieldset>错误消息
在相关输入附近显示错误消息。使用 aria-describedby 将错误与输入关联,使用 aria-live="polite" 向屏幕阅读器朗读错误。
<!-- Accessible error pattern -->
<label for="age">Age:</label>
<input type="number" id="age" name="age"
min="18" max="120" required
aria-invalid="true"
aria-describedby="age-error">
<div id="age-error" role="alert" aria-live="polite"
style="color: red;">
Age must be between 18 and 120.
</div>
<!-- JavaScript for custom validation messages -->
<script>
const ageInput = document.getElementById('age');
ageInput.addEventListener('invalid', (e) => {
if (ageInput.validity.rangeUnderflow) {
ageInput.setCustomValidity('You must be at least 18.');
} else if (ageInput.validity.rangeOverflow) {
ageInput.setCustomValidity('Please enter a realistic age.');
}
});
ageInput.addEventListener('input', () => {
ageInput.setCustomValidity('');
});
</script>10. 移动键盘优化
inputmode 属性让你精细控制移动虚拟键盘,而无需更改输入类型。当你需要特定键盘但希望保持 type="text" 进行自定义验证时,这特别有用。
数字键盘
对于需要数字但不需要 type="number" 行为的字段(如 PIN 码、邮政编码或信用卡号),使用 inputmode="numeric"。
<!-- PIN code (numeric keyboard, no spinners) -->
<label for="pin">PIN Code:</label>
<input type="text" id="pin" name="pin"
inputmode="numeric" pattern="[0-9]{4,6}"
maxlength="6" autocomplete="one-time-code">
<!-- ZIP code -->
<input type="text" name="zip"
inputmode="numeric" pattern="[0-9]{5}"
autocomplete="postal-code">电子邮件键盘
使用 inputmode="email" 显示带有 @ 和 . 按键的优化电子邮件键盘。
<input type="email" inputmode="email"
autocomplete="email">电话键盘
使用 inputmode="tel" 显示完整的电话拨号键盘,适合电话号码输入。
<input type="tel" inputmode="tel"
autocomplete="tel">URL 键盘
使用 inputmode="url" 显示带有 /、. 和 .com 按键的键盘,适合 URL 输入。
<input type="url" inputmode="url"
autocomplete="url">小数键盘
对于可能包含小数点的数字字段(如价格或测量值),使用 inputmode="decimal"。
<!-- Price field with decimal keyboard -->
<label for="amount">Amount ($):</label>
<input type="text" id="amount" name="amount"
inputmode="decimal" pattern="[0-9]*\.?[0-9]+"
placeholder="0.00">11. 表单提交与 FormData API
现代 JavaScript 提供 FormData API 用于程序化表单处理。结合 fetch API,你可以在不刷新页面的情况下提交表单。
基本 FormData 用法
FormData 构造函数接受表单元素并自动收集所有命名输入值。
const form = document.querySelector('#myForm');
const formData = new FormData(form);
// Access individual values
const email = formData.get('email'); // string | null
const files = formData.getAll('photos'); // File[]
// Iterate over all entries
for (const [key, value] of formData.entries()) {
console.log(key, value);
}
// Append extra data
formData.append('timestamp', Date.now().toString());
// Convert to plain object
const data = Object.fromEntries(formData.entries());
// Convert to URL-encoded string
const params = new URLSearchParams(formData).toString();
// "name=John&email=john%40example.com"使用 Fetch API 提交表单
使用 fetch() 异步提交表单数据。当你传递 FormData 对象时,浏览器会自动设置正确的 Content-Type 头。
// Submit as multipart/form-data (for file uploads)
const form = document.querySelector('#uploadForm');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
// Do NOT set Content-Type header manually!
// The browser sets it with the correct boundary
});
const result = await response.json();
console.log(result);
});
// Submit as JSON
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
const response = await fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
});编码类型(enctype)
<form> 上的 enctype 属性控制表单数据在发送前如何编码。三个选项是:
application/x-www-form-urlencoded— 默认值。键值对用&分隔。适合大多数纯文本表单。multipart/form-data— 文件上传必需。每个字段作为带边界标记的独立部分发送。text/plain— 以纯文本发送数据。很少使用;不建议在生产中使用。
<!-- Default: URL-encoded -->
<form method="post" action="/api/contact">
...
</form>
<!-- File upload: Must use multipart -->
<form method="post" action="/api/upload"
enctype="multipart/form-data">
<input type="file" name="document">
<button type="submit">Upload</button>
</form>12. 输入类型对比表
下表总结了所有 HTML 输入类型、其主要用途、移动键盘行为和浏览器支持状态。
| 类型 | 用途 | 移动键盘 | 内置验证 | 浏览器支持 |
|---|---|---|---|---|
text | General text | Standard | pattern, minlength, maxlength | All |
password | Passwords | Standard (masked) | pattern, minlength, maxlength | All |
email | Email addresses | @ key visible | Email format | All |
tel | Phone numbers | Phone keypad | None (use pattern) | All |
url | Web addresses | / and .com keys | URL format | All |
search | Search queries | Search button | None | All |
number | Numeric values | Number pad | min, max, step | All |
range | Value in range | N/A (slider) | min, max, step | All |
date | Calendar date | Date picker | min, max | All modern |
time | Time of day | Time picker | min, max, step | All modern |
datetime-local | Date + time | Date-time picker | min, max | All modern |
month | Year + month | Month picker | min, max | Partial (no Firefox) |
week | Year + week | Week picker | min, max | Partial (no Firefox) |
checkbox | Multiple selection | N/A | required | All |
radio | Single selection | N/A | required | All |
file | File upload | File picker | accept, required | All |
hidden | Hidden data | N/A | None | All |
image | Image submit | N/A | None | All |
color | Color picker | Color palette | None | All modern |
submit | Form submit | N/A | Triggers validation | All |
reset | Form reset | N/A | None | All |
button | Custom action | N/A | None | All |
常见问题
type="button" 和 type="submit" 有什么区别?
type="submit" 在点击时触发表单提交和验证。type="button" 没有默认行为 — 它需要 JavaScript 来执行任何操作。在 <form> 内,没有明确类型的 <button> 默认为 submit,这可能导致意外的表单提交。始终为非提交按钮设置 type="button"。
信用卡字段应该使用 type="number" 还是 inputmode="numeric"?
信用卡号请使用 type="text" 配合 inputmode="numeric"。type="number" 会添加微调箭头、允许科学记数法(如 1e2)并可能去除前导零 — 这些对卡号来说都是不需要的。inputmode 属性可以在没有这些副作用的情况下提供数字键盘。
如何让日期输入必填并设置最小/最大日期?
添加 required 属性以及 YYYY-MM-DD 格式的 min 和 max 属性:<input type="date" required min="2024-01-01" max="2025-12-31">。如果字段为空或日期超出允许范围,浏览器将阻止提交。
HTML 中处理文件上传大小限制的最佳方式是什么?
仅靠 HTML 无法强制文件大小限制。accept 属性限制文件类型(如 accept=".pdf,.docx" 或 accept="image/*"),但大小验证必须通过 JavaScript 在 change 事件中使用 input.files[0].size 来完成,或在服务器端完成。无论是否有客户端检查,始终在服务器端验证。
如何自定义原生 HTML 验证错误消息的样式?
你无法直接为原生浏览器验证工具提示设置样式。但是,你可以使用 :invalid、:valid、:required 和 :user-invalid CSS 伪类来为输入框本身设置样式。对于完全自定义的错误消息,使用约束验证 API:调用 input.setCustomValidity("message") 并使用 input.reportValidity()。或者,在表单上使用 novalidate 禁止原生弹窗,然后完全用 JavaScript 实现自定义验证 UI。
收藏此页面作为 HTML 输入类型和属性的参考。要构建基于 HTML 的表单和表格,请试用我们下方的工具。