field-email--invalid必须挂到字段级block容器上,即<div class="field-email field-email--invalid">,以统一控制label、input、error等子元素样式及aria-invalid等无障碍属性,避免状态不同步。

错误状态必须挂到字段级 block 容器上,不能加在 input 或整个 form 上;否则 label、icon、error 文案无法同步响应,无障碍属性(如 aria-invalid)也会不同步。
field-email--invalid 该挂在哪一层?
必须挂在语义完整的字段容器上,比如 <div class="field-email field-email--invalid">。这个 div 是一个独立可复用的 block,内部包含 label、input、error 等子节点。
- 挂错位置的典型表现:
input边框变红了,但label还是黑的,下方错误文案没显示——因为 CSS 选择器写成了.field-email__input.field-email--invalid,违背 BEM 扁平原则 - JS 只需操作一个 class:
fieldEl.classList.toggle('field-email--invalid', !isValid),干净、可预测 - 禁止写成
field-email__input--invalid:输入框可能被复用于搜索框等非表单场景,此时修饰符语义失效
为什么不能用 form__field--error 这种通用名?
它掩盖了错误类型差异,导致后期样式覆盖困难、JS 切换逻辑复杂、无障碍 ID 难映射。
-
form__field--error看似省事,但密码字段要显示强度条,邮箱字段要加图标,下拉框可能只变文字颜色——硬塞进一个通用类,后期必然要加!important或嵌套覆盖 - 正确做法是按字段类型细化:
field-email--invalid-format、field-password--weak、field-select--required-missing - 共性样式抽到基础类:
field-email和field-password共享边框过渡、字体大小等,状态类只负责“变化部分”
:invalid 伪类和 BEM 状态类怎么协同?
别互斥,要分层:浏览器原生 :invalid 做轻量兜底反馈,BEM 状态类由 JS 主动控制,承担业务逻辑和周边元素联动。
立即学习“前端免费学习笔记(深入)”;
-
:invalid在移动端 Safari 支持差,且只对已获焦+校验失败的字段生效;空的required字段初始就是:valid,根本触发不了 - 建议仅用
:invalid控制最基础视觉:.field-email__input:invalid { border-color: #f00; } - BEM 类必须能覆盖它:
.field-email--invalid-format .field-email__input { border-color: #d32f2f; background-image: url("data:image/svg+xml,%3Csvg%3E"); } - 确保
aria-describedby指向正确的id,而不是靠 class 名堆砌多个修饰符(如field-email--empty--format--domain)
最容易被忽略的是:验证状态不是布尔值,而是多维度信号——字段类型、错误原因、是否已触达(touched)、是否提交过(submitted)。BEM 修饰符只是它的 CSS 显形出口,背后必须有 JS 校验函数统一决策输出,不能靠 class 名字符串拼接来模拟状态机。


















