BEM修饰符必须用双短横线--分隔,如btn--disabled;禁止使用-或_,避免嵌套如btn--primary--loading,多个状态需空格组合并显式定义CSS叠加效果。

修饰符必须用 -- 分隔,不能写成 - 或 _
BEM 里修饰符的唯一合法分隔符是双短横线 --,比如 btn--disabled 是对的,btn-disabled 或 btn_disabled 都不是修饰符——它们会被解析为独立类名,DevTools 看不出状态语义,构建工具可能误删,协作时别人会当成新组件去改。
常见错误:btn--primary--loading 这种嵌套写法非法,BEM 不允许修饰符再修饰修饰符;btn-primary-disabled 是耦合命名,既破坏分离原则,又让 JS 控制时得拼字符串,极易漏空格或覆盖其他状态。
-
btn--loading、btn--error、btn--success是合规写法 - 布尔型状态可用
is-前缀,如modal--is-open,但按钮更倾向阶段词:btn--submitting比btn--is-submitting更直接 - 禁止用
btn--pending这类模糊业务词,它不说明是否禁用点击、是否显示 spinner;btn--loading才能一眼对应视觉反馈和行为抑制
多个状态共存时,用空格组合,CSS 必须显式声明叠加效果
BEM 允许多个修饰符同时存在,比如 class="btn btn--primary btn--loading",但 CSS 不会自动合并规则——btn--loading 设了 cursor: wait,btn--disabled 写了 pointer-events: none,最终表现取决于层叠顺序,而不是 class 在 HTML 中的书写顺序。
- JS 添加/移除必须用
element.classList.toggle('btn--loading', isLoading),避免手动拼接字符串 - 不能靠“写在后面”碰运气,要在 CSS 中明确写出组合效果,例如:
.btn--loading.btn--disabled { opacity: 0.6; } - 状态修饰符必须绑定可验证的视觉或行为表现,别用
--network-error把网络层细节暴露到样式层
修饰符不是断点开关,也不是伪类替代品
修饰符只表达组件当前意图状态,比如 card--layout-stack 表示“采用堆叠布局”,而不是“在小屏下才堆叠”。媒体查询逻辑该由 @media 处理,修饰符只是 CSS 层叠的钩子。
立即学习“前端免费学习笔记(深入)”;
同理,:valid/:invalid 伪类不可靠:空的必填字段初始就是 :valid,Safari 对 :user-invalid 支持差,且浏览器不响应未交互字段的校验状态。状态必须由 JS 校验函数驱动并主动添加修饰符。
- 表单字段推荐用
form-field--invalid,作用在容器上,统一控制子元素样式和aria-invalid属性 - 评分组件中,悬停高亮需 JS 计算位置并动态加
rating__star--hovered,不能只靠:hover - 禁用态应作用于 Block(如
rating--readonly),而非单个rating__star元素
元素级修饰符可以存在,但不能跨块或嵌套过深
修饰符可以加在元素上,比如 btn__icon--large 合法,表示“按钮内图标的放大变体”。但 btn__icon--primary 和 btn--primary__icon 都不对——后者语法无效,BEM 解析器直接忽略。
常见翻车点是把语义和结构混写,比如 header-btn 或 user-card-button,这类名字一换场景就得重写;还有 card__content__title__link 这种三级嵌套,BEM 不允许,title 应该是独立块。
- 子元素用双下划线
__,如btn__text;修饰符用双短横--,如btn--small - 禁止跨块组合,比如
header__button--submit是反模式;button button--submit才是正确方式 - 图标等子元素必须是
btn的直接子节点,不能套在div里再加 class
实际项目中最容易被忽略的,是修饰符的语义边界——它不是随便贴的标签,而是 UI 层可感知、可验证的行为信号。写错一个 -- 或多嵌一层 __,问题不会立刻报错,但半年后你 debug 时会花三倍时间搞不清那个 btn-loading 到底是不是状态类。


















