状态修饰符必须挂载在block根元素上,如alert--success;禁止加在子元素,否则导致样式断裂、js混乱、无障碍语义丢失;仅允许语义化命名,禁用视觉描述类;表单需按字段细化状态类,初始态不依赖状态类。

success 和 error 修饰符必须挂载在 Block 根元素上
把 alert--success 或 alert--error 加在子元素(比如 alert__content 或 alert__icon)上,会导致样式断裂、JS 控制混乱、无障碍语义丢失。状态是整个提示框的业务含义,不是某个局部的视觉变化。
常见错误现象:alert__content--success 被加上后,图标颜色没变、边框没更新、屏幕阅读器读不出“成功”语义——因为 aria-live 和 role="alert" 是绑定在根元素上的,修饰符挂错位置就断开了这层关联。
- 正确写法:
<div class="alert alert--success">... <li>JS 切换只需操作一个 class:<code>alertEl.classList.replace('alert--error', 'alert--success') - 所有视觉差异(背景、边框、图标色、文字色)都在
.alert--success规则里统一声明,不分散到子选择器中 - 只允许使用语义化状态名:
alert--success、alert--error、alert--info、alert--warning - 禁止用
--red、--icon-right、--large等描述性词 - 颜色由 CSS 自定义属性控制,例如
--alert-success-bg: #155724,而非硬编码进类名 - 字段级 Block 必须存在,如
field-email、field-password - 错误状态挂载在该 Block 容器上:
<div class="field-email field-email--invalid-format"> <li>共性样式抽到基础类(如 <code>field-email定义边框过渡),状态类只负责“变化部分” - 避免
form__field--error这种泛化命名,它掩盖了字段特异性,也导致 JS 切换逻辑臃肿 -
form-field--invalid仅在 JS 校验返回false时添加,返回true或undefined时移除 - 初始态不加任何修饰符,靠
:not(:placeholder-shown)或form-field--touched表达是否已输入 - 需要视觉确认的场景(如密码强度条),可用
form-field--touched form-field--valid组合,但--valid不参与校验逻辑判断
不能用 color 或 position 类名命名状态修饰符
alert--green 或 alert--left-icon 这类名字看似直观,实则埋下长期维护雷。设计规范一改,类名就失效;RTL 布局下 --left-icon 会反向错位;更重要的是,无障碍工具无法将 “green” 映射为 “success” 的语义。
状态修饰符必须表达稳定、可预期的业务含义,而不是视觉表现。BEM 规范要求它和产品/设计系统定义的状态对齐。
表单内错误提示要按字段类型细化状态类
通用的 alert--error 在表单场景下不够用。邮箱格式错、密码强度弱、必填项为空,这三类错误的视觉反馈和交互逻辑完全不同——统一用一个类,后期只能靠 !important 或嵌套覆盖来打补丁。
验证状态不是布尔值,而是多维度信号:字段类型 + 错误原因 + 用户交互阶段。BEM 要求把这种差异显式编码进类名。
初始态不依赖状态类,form-field--invalid 是唯一主动反馈类
不要同时定义 form-field--valid 和 form-field--invalid。验证结果是动态的,“有效”不等于“已通过校验”,更不等于“可提交”。用户刚输完合法邮箱,立刻加 --valid,但其他字段还是空的,整个表单其实无效——这种语义误判会破坏用户信任。
更稳妥的做法是只保留 form-field--invalid 作为 JS 主动触发的反馈类,其余状态靠默认样式或 form-field--touched 区分。











