12k
All articles

开发者常忽略的原生 HTML 验证属性

借助 formnovalidate、pattern、autocomplete 等原生 HTML 属性构建表单,可减少自定义 JavaScript 并改善无障碍性。

OpenReplay Team
OpenReplay Team
开发者常忽略的原生 HTML 验证属性

你正在编写自定义 JavaScript 来验证表单,而这些工作 HTML 本可以原生处理。大多数前端开发者都知道 requiredpattern,但平台提供的功能远不止这些——这些属性可以减少代码量、改善可访问性,并在无需框架依赖的情况下创建更好的用户体验。

本文介绍了你可能忽略的 HTML 验证属性,以及使原生表单验证真正有用的 CSS 和 JavaScript 特性。

核心要点

  • form 属性允许控件通过 ID 与表单关联,无论 DOM 位置如何,从而消除复杂的包装结构。
  • 按钮级属性如 formactionformmethodformnovalidate 让单个表单根据提交按钮的不同而表现不同。
  • 现代 autocomplete 标记(new-passwordone-time-codewebauthn)提高自动填充准确性并触发浏览器功能,如密码生成器。
  • CSS :user-invalid 解决了”页面加载时显示红色边框”的问题,仅在用户交互后显示错误。
  • 约束验证 API(setCustomValidity()checkValidity()reportValidity())在原生验证需要增强时提供编程控制。

form 属性:表单外的控件

需要在页面头部放置提交按钮,而表单位于主内容区?form 属性允许任何控件通过 ID 与表单关联,无论 DOM 位置如何。

<form id="checkout">
  <input type="email" name="email" required>
</form>

<button type="submit" form="checkout">完成购买</button>

这消除了包装器的复杂操作,并且适用于 input、button、select 和 textarea 等元素。

你应该了解的按钮级覆盖

单个表单可以根据提交按钮的不同而表现不同。这些属性会覆盖父表单的设置:

  • formaction — 提交到不同的 URL
  • formmethod — 使用 GET 而非 POST(或反之)
  • formenctype — 更改文件上传的编码方式
  • formtarget — 在新标签页中打开响应
  • formnovalidate — 完全跳过验证

formnovalidate 属性值得特别关注。它对于”保存草稿”按钮至关重要,因为在这种情况下不完整的数据是可以接受的。

带有有用错误消息的模式验证

pattern 属性接受正则表达式,但浏览器默认显示通用错误。将其与 title 配对以提供上下文:

<input type="text" 
       pattern="[A-Z]{2}[0-9]{6}" 
       title="格式:两个字母后跟六位数字(例如,AB123456)">

注意:当在 type="email" 等输入上设置 multiple 时,模式会应用于每个单独的值,而不是整个逗号分隔的字符串。

现代 autocomplete 标记

除了 onoff,autocomplete 接受语义标记以提高自动填充准确性:

  • autocomplete="new-password" — 触发密码生成器
  • autocomplete="one-time-code" — 针对短信验证进行优化
  • autocomplete="webauthn" — 标识通行密钥凭据字段

这些标记减少了摩擦,并向浏览器和密码管理器传达意图(请参阅 HTML 规范中的完整标记列表和 MDN 的 autocomplete 文档)。

用于国际化的 dirname 属性

在支持从右到左语言时,dirname 会自动提交文本方向和值:

<input type="text" name="comment" dirname="comment.dir">

表单会同时提交 comment(值)和 comment.dir(ltrrtl)。这对于正确渲染用户生成的内容至关重要。

readonly 的细微差别

一个常见的误解:readonly 字段参与表单提交,但在验证方面表现不同。它们会提交值并且可以获得焦点。

然而,在现代 HTML 中,readonly 控件被排除在约束验证之外。这意味着在当前的常青浏览器中,requiredpatternminmax 等属性在 readonly 输入上会被验证忽略。

如果你需要显示一个值而不允许编辑不提交它,disabled 通常是更好的选择——尽管禁用字段不会提交其值。

用于现代表单用户体验的 CSS :user-invalid

经典的 :invalid 伪类会立即触发,在用户交互之前就显示错误。较新的 :user-invalid 仅在用户交互后匹配——解决了”页面加载时显示红色边框”的问题。

input:user-invalid {
  border-color: #dc3545;
}

input:user-valid {
  border-color: #28a745;
}

这在无需 JavaScript 时序逻辑的情况下创建了更好的用户体验。浏览器支持现在在常青浏览器中已经很稳定(请参阅 MDN 上的 :user-invalid)。

约束验证 API

当原生验证需要增强时,约束验证 API 提供编程控制:

  • checkValidity() — 返回布尔值,失败时触发 invalid 事件
  • reportValidity() — 返回布尔值并显示原生错误 UI
  • setCustomValidity() — 设置自定义错误消息
const password = document.querySelector('#password');
const confirm = document.querySelector('#confirm');

confirm.addEventListener('input', () => {
  confirm.setCustomValidity(
    password.value !== confirm.value ? '密码必须匹配' : ''
  );
});

调用 setCustomValidity('') 以清除错误——传递任何非空字符串都会将字段标记为无效。

原生验证的不足之处

原生验证处理大多数情况,但有其局限性:

  • 跨字段验证(密码确认)需要 JavaScript
  • 错误消息样式由浏览器控制
  • 复杂的异步验证(用户名可用性)需要自定义代码

策略是:使用 HTML 验证属性作为基线,使用 CSS :user-invalid 进行样式设置,并仅在必要时添加约束验证 API。

结论

原生表单验证已经显著成熟。本文介绍的属性——form、按钮级覆盖、dirname、现代 autocomplete 标记——在默认情况下改善可访问性的同时,消除了大量自定义 JavaScript。

审查你现有的表单。你可能会发现 HTML 可以原生处理的验证逻辑,以及 CSS :user-invalid 可以在不需要任何事件监听器的情况下解决的用户体验问题。

常见问题

我可以样式化原生浏览器验证错误消息吗?

原生验证错误气泡的样式选项有限,由浏览器控制。你无法直接使用 CSS 对其进行样式化。对于自定义样式的错误消息,你可以在表单上使用 novalidate 属性禁用自动验证 UI,然后使用约束验证 API 检查有效性并显示你自己的错误元素。validationMessage 属性让你可以访问浏览器生成的错误文本。

原生 HTML 验证是否适用于 React 或 Vue 等 JavaScript 框架?

是的,原生验证属性在框架中有效,因为它们渲染标准 HTML。然而,框架通常以不同的方式管理表单状态,这可能与原生验证冲突。许多开发者使用 novalidate 属性并通过框架状态处理验证。你仍然可以在组件中以编程方式利用约束验证 API 来实现混合方法。

checkValidity() 和 reportValidity() 之间有什么区别?

两种方法都返回一个布尔值,指示元素是否通过验证约束。区别在于副作用:checkValidity() 仅在失败时触发 invalid 事件,而 reportValidity() 还会显示浏览器的原生错误消息 UI。当你想静默检查有效性时使用 checkValidity(),当你想让浏览器向用户显示错误反馈时使用 reportValidity()。

如何仅使用 HTML 验证两个密码字段是否匹配?

你无法仅使用 HTML 属性验证两个字段是否匹配。这需要 JavaScript。通过向确认字段添加 input 事件监听器来使用约束验证 API,然后在值不同时调用 setCustomValidity() 并传入错误消息,或在值匹配时传入空字符串。这将你的自定义逻辑与原生验证系统集成在一起。

Open-source session replay

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.