验证失败后自动聚焦首个错误输入框需两步:先准确定位,遍历表单元素过滤禁用、隐藏及无校验属性项,取首个 validity.valid 为 false 的字段;再可靠聚焦并滚动可见,须在用户手势同步回调中调用 focus(),必要时配合 readonly 切换、select() 和 scrollIntoView({block: 'center'})。

验证失败后自动聚焦到第一个错误输入框,核心是两件事:准确定位错误字段 + 可靠触发聚焦与可见性。不能只调 focus() 就完事,尤其在移动端或复杂布局下容易失效。
找到第一个校验失败的输入框
浏览器原生 form.checkValidity() 只返回 true 或 false,不告诉你哪个错了。必须手动遍历:
- 用
form.querySelectorAll('input, select, textarea')拿所有候选元素 - 过滤掉这些项:
-
input.disabled === true -
input.type === 'hidden' -
!input.willValidate(关键!没设required、type="email"等校验属性的字段,validity无意义)
-
- 对剩下每个元素,检查
!input.validity.valid - 返回第一个满足条件的元素
示例代码:
function getFirstInvalidField(form) {
const fields = form.querySelectorAll('input, select, textarea');
for (const field of fields) {
if (field.disabled || field.type === 'hidden' || !field.willValidate) continue;
if (!field.validity.valid) return field;
}
return null;
}聚焦时确保真正生效(尤其移动端)
单纯 input.focus() 在 iOS Safari 和部分安卓 WebView 中常静默失败——因为浏览器禁止非用户手势触发键盘弹出。
立即学习“Java免费学习笔记(深入)”;
安全做法是:
- 在用户点击/触摸事件的同步回调内立即调用
focus() - 若必须异步(如 AJAX 校验后),可临时加
readonly再移除:input.setAttribute('readonly', ''); input.focus(); input.removeAttribute('readonly'); - 配合
input.select()让光标更明显(用setTimeout(() => input.select(), 0)避免竞争)
滚动到可视区域,别让用户找
聚焦 ≠ 看见。如果输入框在折叠区、tab 面板里、或页面底部,用户根本不知道哪错了。
必须成对使用:
input.focus();
input.scrollIntoView({ block: 'center', behavior: 'smooth' });注意:
- 顺序不能反:先
focus(),再scrollIntoView() -
block: 'center'比默认start更稳妥,避免被顶部导航栏遮挡 - 若父容器有
overflow: hidden或transform,scrollIntoView()可能失灵,需手动计算滚动位置
多 tab 表单要限定查找范围
验证失败却跳到第一个 tab 的错误框?说明你用了全局查询。
正确做法:
- 先定位当前激活的 tab 面板,例如:
const $active = $('.layui-tab-content .layui-show')(Layui)或document.querySelector('.tab-panel.active')(自定义) - 再在这个范围内查:
$active.find('input[lay-verify], select[lay-verify]')或activePanel.querySelectorAll('input, select') - 遍历该子集,而非整个表单
不复杂但容易忽略


















