form-field--invalid必须挂在字段级容器上,如,不可作用于input或form元素;它作为唯一js主动控制的修饰符,驱动label、message、icon等关联样式,且与form-field--valid互斥,禁用多修饰符堆砌和长串命名。

form-field--invalid该挂在哪一层
必须挂在字段级容器上,比如 <div class="form-field">,而不是 <code>input 或整个 form。一个字段出错就让整表单变红,既语义错乱,也干扰用户定位问题。
常见错误是把修饰符加在 input 上:form__input--error——这破坏 BEM 封装边界,样式只能作用于 input 本身,无法同步控制 label 颜色、错误文案显隐、icon 状态等关联行为。
-
form-field--invalid是唯一需要 JS 主动添加/移除的类,所有视觉反馈都靠它驱动 - 对应 CSS 写成:
.form-field--invalid .form-field__input控边框、.form-field--invalid .form-field__label控颜色、.form-field--invalid .form-field__message控显隐 - 禁止给
form元素加form--invalid,那等于把“单个字段失败”升维成“整个表单失败”
为什么不能同时用 form-field--invalid 和 form-field--valid
验证状态互斥,一个字段同一时刻只能处于“未校验”“无效”“有效”之一。但 form-field--valid 极易引发语义误判:用户刚输完合法邮箱,JS 立即加了这个类,可此时表单还没提交,其他字段仍是空的——业务逻辑上它根本不“有效”。
更现实的问题是信任错乱:空字段没获焦前显示绿色边框(因 :valid 生效),用户以为已通过;或输入后立刻变绿,提交时后端校验失败又跳红,造成预期崩塌。
- 只保留
form-field--invalid作为主动反馈类,JS 校验返回false时添加,返回true或undefined时移除 - 初始态不依赖任何修饰符,靠
.form-field__input:not(:placeholder-shown)或form-field--touched区分是否已输入 - 如需密码强度等实时确认场景,可用
form-field--touched form-field--valid组合,但form-field--valid必须配合--touched使用,绝不单独出现
多个验证规则共存时,Modifier怎么命名才不爆炸
别堆砌 form-field--required --email --max-len 这类多修饰符。CSS 权重会失控,改一个可能意外影响另一个;更重要的是,它把校验逻辑泄漏到类名里,JS 得反复拼字符串,维护成本指数上升。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
BEM 修饰符不是日志,而是契约:一个字段在同一时刻只有一个对外暴露的状态信号。
- 统一用
form-field--invalid表达“校验失败”,具体错误类型由form-field__message的文本内容决定 - 如需区分错误来源(比如前端格式错 vs 后端冲突),可用
form-field--backend-error这类有限枚举,但必须由 JS 统一决策后设置,不靠规则叠加 - 禁止写
form-field--email-format-invalid这种长串修饰符——它不可复用、难测试、权重高,且一旦规则调整就得全量改类名
如何让 :invalid 伪类和 BEM Modifier 协同工作
:invalid 是被动响应,只在字段“脏了”且校验失败时生效,空的 required 字段初始就是 :valid,根本无法满足“空字段显灰边框+提示”的设计需求。移动端 Safari 对 :user-invalid 支持极差,纯 CSS 方案在关键路径上不可靠。
正确做法是分层:用 :invalid 做最轻量兜底(比如 input 边框变红),用 BEM 类做主动、可控、可扩展的反馈。
-
:invalid仅用于无 JS 场景或降级 fallback,样式要足够轻(避免影响布局、不控制周边元素) - BEM 类必须能覆盖
:invalid,建议所有状态样式都用单个类选择器定义,不嵌套,确保优先级可控 -
:invalid无法触发aria-describedby关联,BEM 类则可由 JS 同步更新aria-invalid="true"和aria-describedby属性
form-field--invalid,就意味着背后必须有一致的、可预测的校验函数返回值驱动它——不是“有没有错”,而是“错得是否值得让用户立刻知道”。










