表单字段的 block 名必须用语义化、可复用的组件名,如 field-email、field-password,表示完整功能单元;禁止使用 form__email、input-email 等非业务语义或错位命名。

表单字段的 block 名该叫什么
必须用语义化、可复用的组件名,比如 field-email、field-password,而不是 form__email 或 input-email。前者是独立 block,后者要么挂错作用域,要么混淆了元素层级。
常见错误现象:form__input 这类命名会让 JS 操作时无法精准控制 label 和 error;更糟的是,input-email 不符合 BEM 三段式,input 是 HTML 标签名,不是业务块名,团队协作时根本没法对齐上下文。
-
field-email表示“邮箱输入字段”这个完整功能单元,含 label、input、error 等所有子节点 - 禁止用位置或样式命名,如
form-left-field或field-red-border - 如果字段带图标(如搜索放大镜),应作为
field-search__icon,而非field-search-icon(少一个下划线就不是 BEM)
验证状态 class 该加在哪个 DOM 节点上
必须加在 block 容器上,即 field-email 这个 <div> 上,不能加在 <code><input> 或整个 <form></form> 上。
挂错位置的后果很直接:校验反馈失控、复用困难、无障碍属性(如 aria-invalid)不同步。比如把 field-email--invalid 加到 <input> 上,CSS 就得写 .field-email__input.field-email--invalid,这违背 BEM 扁平原则,也导致 JS 必须手动同步操作 label 和 error 元素。
立即学习“前端免费学习笔记(深入)”;
-
field-email--invalid应作用于容器,CSS 内统一控制:field-email__input边框、field-email__error显隐、field-email__label颜色 - 不要堆砌多个修饰符,如
field-email--empty--format--domain——权重爆炸、JS 切换逻辑复杂、无障碍 ID 难映射 - 区分错误类型靠 JS 动态更新
aria-describedby指向不同id,不是靠 class 名变体
label 和 input 的 HTML 结构怎么写才合规
BEM 类名再标准,结构不对,屏幕阅读器和 :focus-within 就失效。必须确保语义绑定清晰、可检测。
推荐显式 for/id 绑定:<label for="field-email__input"></label> + <input id="field-email__input" class="field-email__input">。ID 必须与 __input 后缀一致,这是 axe 和 Lighthouse 能正确识别的关键。
- 嵌套方式也可行:
<label class="field-email__label">邮箱<input class="field-email__input"></label>,但前提是整个结构包裹在<div class="field-email"> 内 <li>禁止混用:一半用 <code>for/id,一半用嵌套,工具会报「label not associated with a control」 -
field-email__label和field-email__input必须同属一个field-emailblock,否则 CSS 的:focus-within无法触发容器状态 - 最终状态必须由校验函数返回值驱动:
field-email.classList.toggle('field-email--invalid', !isValid) - 哪怕只做前端校验,也要用 JS 主动设置 class,而不是等伪类被动触发
- 伪类可作降级补充(如
.field-email__input:invalid加个红边),但不能作为主控逻辑
为什么不用 :valid/:invalid 伪类替代 JS 控制
浏览器原生伪类在关键场景下基本不可靠,纯靠它做验证反馈等于放弃控制权。
:invalid 对空必填字段不生效,除非用户已聚焦并失焦(touched);但设计常要求“初始为空就显示浅灰边框+提示文字”。:user-invalid 在 iOS Safari 上支持极差,连基础邮箱格式错都常不响应。更重要的是,校验逻辑常依赖异步(如用户名是否已存在),伪类完全无法介入。
field-email__button 当成按钮元素,其实它该属于独立的 button block;一旦跨块命名,BEM 的隔离性就塌了一半。


















