判断UI单元该为Block还是Element,关键看能否脱离上下文独立存在、是否具备跨场景复用价值:.modal是Block,.modal__header是Element;布局容器如.container不合格,合格Block须为“名词+角色”组合,如.notification-banner。

如何判断一个UI单元该定义为 Block 还是仅作为 Element
关键看它能否脱离当前上下文独立存在、是否具备跨场景复用价值。比如 .modal 是 Block,因为它在表单页、详情页、设置弹窗里都可原样复用;而 .modal__header 就只能是 Element,删掉 .modal 它就失去语义和样式基础。
常见错误是把布局容器当 Block:.container、.row、.section-2 都不合格——它们不表达功能,只描述结构或位置,一改布局就得重写所有相关 CSS。
- 合格的 Block 名必须是「名词 + 角色」组合,如
.notification-banner、.pagination-controls - Element 名不能带父级冗余:
.card__card-title❌,应为.card__title✅ - 如果某个“子元素”(如
.badge、.avatar)在多个 Block 中高频出现,它本身就该升为独立 Block
Modifier 命名为什么不能用 --loading 或 --blue
因为 --loading 暴露实现细节,--blue 绑定视觉值,二者都会导致样式与 JS 状态或设计系统强耦合。按钮加载中状态可能由 isPending 控制,但主题换色时,--blue 得全局搜替换,而 --primary 只需改一次 CSS 变量。
修饰符名必须可预测、可枚举、与业务逻辑对齐:
立即学习“前端免费学习笔记(深入)”;
- ✅ 推荐:
--disabled、--primary、--size-large - ❌ 禁止:
--v2、--left、--margin-8、--mobile(响应式断点不属于 Modifier 职责) - Element 修饰符要挂对位置:
.button__label--hidden✅,.button--primary__label❌(语法非法,且语义混乱)
SCSS 中怎么写才不破坏 BEM 封装性
BEM 的核心是输出扁平类名,不是写嵌套结构。Sass 的 & 很方便,但一不留神就会编译出后代选择器,破坏作用域隔离。
正确写法只允许单层嵌套:&__elem 和 &--mod,绝不用 &__elem__icon 或 &__elem &__icon:
.button {
&__text { font-weight: 600; }
&--large { padding: 12px 24px; }
}错误写法会产出 .button__text .button__icon 这种后代选择器,一旦 DOM 结构微调,样式就失效:
.button {
&__text {
&__icon { /* 编译后是 .button__text .button__text__icon */ }
}
}- 所有 Block 样式必须独占一个文件,如
_button.scss,禁止跨 Block 引用(如在_button.scss里写.modal__close) - 禁用空格连接的选择器:哪怕结构再深,CSS 输出里不能出现
.block__item .block__icon - 遇到“元素里的图标”,优先拆成新 Block:
.status-badge,而不是.table-cell__status__icon
在 CSS-in-JS 或 CSS Modules 中如何保持 BEM 语义
BEM 不依赖传统 CSS 文件路径,而是解决「样式归属」问题。在 CSS Modules 中,import styles from './Button.module.scss' 后,必须只暴露 Block 类名,Element/Modifier 通过组合注入,而非让调用方直接取 styles.button__icon。
否则边界立刻模糊:有人在 Modal 组件里手写 className="button__icon",等于绕过 Block 封装。
- 组件内部用
clsx组合:className={clsx(styles.button, props.loading && styles['button--loading'])} - 禁止字符串拼接:
className={`button ${props.active ? 'button--active' : ''}`❌ - 用 ESLint 插件
eslint-plugin-css-modules校验:确保 JSX 中出现的类名,全部来自当前模块声明的 BEM 模式 - 第三方样式(如 Ant Design)必须包裹在 wrapper Block 里隔离,避免污染命名空间
BEM 最容易被忽略的点,是它从来不只是命名规则——它要求 HTML 结构、CSS 输出、JS 类名控制三者严格对齐。一个 --disabled 修饰符若没对应 JS 切换逻辑,或没在 HTML 中显式添加,那它就是个死样式。


















