一聚教程网:一个值得你收藏的教程网站

热门教程

如何在大型项目中制定统一的CSS BEM命名规范?

时间:2026-08-22 13:01:49 编辑:袖梨 来源:一聚教程网

真正落地BEM需卡住block唯一性、element直属性、modifier可维护性;block须带业务前缀(如nc-button)并与组件名严格一致,禁止嵌套element(user-card__avatar__icon❌)和视觉型modifier(button--red❌),须通过stylelint、Git Hook、CI三阶校验。

直接定死 block__element--modifier 格式不等于有了规范——真正卡住协作的,是 block 名是否唯一、element 是否越界、modifier 是否可维护。没校验工具链兜底,三天后就会出现 user-card__titleuser-card-title 并存。

Block 名必须带业务前缀且与组件名完全一致

buttoncard 作 block 名,等于主动放弃命名空间隔离。Ant Design、Bootstrap、甚至你自己的 ds-button 都可能撞车。

  1. 推荐格式:nc-button(nc = team/product 缩写)、myapp-user-cardds-input
  2. 禁止:base-buttoncommon-cardui-header——这些词在 PR 里无法被唯一索引
  3. 文件夹名、组件名、CSS 文件名、BEM block 名必须全等:/components/user-profile-card/user-profile-card.cssuser-profile-card
  4. 设计稿里叫“用户资料卡片”,代码里就不能缩写成 profile-carduser-card,否则 Figma 插件导出类名和实际 CSS 对不上

Element 只能直属 Block,禁止嵌套或语义冗余

user-card__avatar__icon 看似“更细”,实则破坏 BEM 基础契约:元素不可再拆解归属。它不是 DOM 深度标记,而是逻辑归属声明。

  1. 正确:user-card__avataruser-card__avatar--compactuser-card__avatar-icon(把 icon 视为 avatar 的视觉变体)
  2. 错误:user-card__avatar__icon(编译后无效,stylelint 直接报错)、user-card__user-card-title(语义重复,“user-card-”前缀无意义)
  3. 如果 avatar 自身具备独立交互或复用逻辑,就该升格为新 block:avatar,而非强行挂在 user-card
  4. 禁止用类型词替代角色:user-card__divuser-card__span 是反模式;应是 user-card__contentuser-card__badge

Modifier 必须表达稳定状态,不能是视觉快照

button--red 这类 modifier 看似直观,但换主题时根本没法映射——红色可能是 primary、danger、highlight,取决于上下文。它不是状态,是颜色值快照。

  1. 正确:button--primarybutton--disabledinput--searchmodal--fullscreen
  2. 错误:button--bluecard--largetext--14px——这些值会随断点、主题、设备变化,无法长期维护
  3. Modifier 必须与 class 共存,不能靠 JS 动态塞变量:--is-loading 是反模式;应保持 button--loading 类,并用变量驱动其样式:.button--loading { background-color: var(--ui-button-bg-loading); }
  4. 禁止嵌套 modifier:button--primary--disabled 不合法;应并列使用:button button--primary button--disabled

工具链必须把 BEM 当语法边界来校验,不是风格提醒

靠 Code Review 或文档提醒,拦不住手滑。违规类名必须在保存、提交、构建三个环节就被拦截,否则每天都在污染边界。

  1. stylelint-selector-bem-pattern 插件,配置 {"styleType": "bem"},它会立刻报错:.header .logo(结构选择器)、.btn-primary(非 BEM 格式)、CardTitle(大驼峰)、_input(下划线开头)
  2. CI 流程中强制跑:npx stylelint "**/*.{css,scss}",失败即阻断合并
  3. 禁用 SCSS 嵌套生成后代选择器:&__input { &__icon {} } 会产出 block__input__icon,违反规则;只允许单层:&__input {} &--compact {}
  4. JS 中拼接类名必须封装:cn('input', 'disabled') 而非 `button__${e}--${m}`——后者漏空格、错连字符、大小写不一致,在 Linux 构建环境直接挂掉

最常被忽略的一点:BEM 不是给类名“加长”,而是让每个字符都承担语义责任。user-profile-card__avatar--compact 里少一个 -、多一个 _,都不是“写错了”,而是让工具链失效、团队搜索失焦、重构路径断裂。它必须像函数签名一样精确。

热门栏目