form-field--invalid 是唯一应由 JS 控制的修饰符,用于统一驱动容器、label、input、message 和 icon 的视觉与语义状态,确保可访问性与一致性。

form-field--invalid 是唯一该由 JS 主动控制的修饰符,其他所有视觉反馈都应基于它派生;别用 :invalid 伪类驱动完整错误流,它不控容器、不传语义、不兼容 Safari。
为什么不能直接用 :invalid 控制整个错误提示链
浏览器原生 :invalid 只在字段“脏了”且校验失败时才触发,空的 required 字段初始就是 :valid,根本不会显示红边框或错误文案。移动端 Safari 对 :user-invalid 支持极差,关键路径不可靠。:invalid 只能作用于 input 元素本身,无法让 label 变色、icon 切换、form-field__message 显隐——这些必须靠同一个状态信号统一驱动。
常见错误现象:
- 用户没输任何内容,表单却显示绿色边框(因
:valid误判) - 错误文案始终不出现,只看到 input 边框变红(因没挂状态到容器)
- 屏幕阅读器读不出错在哪(
:invalid不自动关联aria-describedby)
form-field--invalid 必须挂在字段级容器上,不是 input 也不是 form
结构必须是:。JS 只需操作这一个类:fieldEl.classList.toggle('form-field--invalid', !isValid),干净可预测。
禁止写法:
-
form__input--error:破坏 BEM 封装,input不是独立功能单元,改不了 label 和 message -
form--invalid:一个字段错就整表单变红,语义错乱,用户无法定位问题 -
form-field--required--email--max-len:堆砌修饰符,CSS 权重失控,JS 拼字符串维护爆炸
错误文案和关联样式怎么靠 form-field--invalid 统一控制
CSS 必须用后代选择器下发,把状态从容器透出到内部各元素:
/* 边框 */
.form-field--invalid .form-field__input {
border-color: #e74c3c;
}
<p>/<em> label 颜色 </em>/
.form-field--invalid .form-field__label {
color: #c0392b;
}</p><p>/<em> 错误文案显隐 </em>/
.form-field--invalid .form-field__message {
display: block;
opacity: 1;
}</p><p>/<em> 图标状态(如 SVG) </em>/
.form-field--invalid .form-field__icon {
background-image: url('error-icon.svg');
}</p>
初始态不依赖任何修饰符,靠 .form-field__input:not(:placeholder-shown) 或 form-field--touched 区分是否已输入;form-field--valid 仅限密码强度等明确需实时确认的场景,且必须与 --touched 组合使用,绝不单独出现。
多个验证规则共存时,怎么避免修饰符命名爆炸
BEM 修饰符不是日志,它是契约:一个字段同一时刻只能对外暴露一个状态信号。具体错误类型(空、格式错、域名不合法)由 form-field__message 的文本内容决定,而不是塞进类名里。
安全做法:
- JS 校验函数返回
false→ 添加form-field--invalid - 返回
true或undefined→ 移除form-field--invalid - 错误文案动态插入:
messageEl.textContent = getErrorMessage(ruleResult)
最易被忽略的一点:form-field--invalid 必须配合 aria-invalid="true" 和 aria-describedby 才算完整;光有 CSS 类,无障碍支持就断掉了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











