前端开发中的 BEM 国际命名规范:让 CSS 不再"打架"

0 阅读4分钟

先从一个"惨案"说起

你是不是也经历过这样的场景:

你给按钮写了个 .btn 样式,美滋滋。结果第二天,同事也在他的模块里写了个 .btn,样式完全不一样。两个 .btn 在页面上相遇,CSS 层叠规则开始"打架",按钮变得四不像。你俩对着屏幕面面相觑——这锅到底谁的?

这就是 CSS 命名混乱的经典现场。而 BEM,就是来终结这场混乱的"和平条约"。


BEM 是什么?

BEM 是 Block(块)、Element(元素)、Modifier(修饰符) 三个单词的缩写,由俄罗斯 Yandex 公司提出,是一套 CSS 类名命名方法论。

它的核心思想很简单:把页面拆成独立的组件块,用一套统一的命名规则,让每个类名都能"自报家门"。


三个角色,各司其职

🧱 Block(块)—— 独立的组件

Block 是页面上独立、可复用的组件,它不依赖任何其他东西,自己就能活得很好。

.header { }
.menu { }
.button { }
.card { }

类比:Block 就像乐高积木里的一块"车轮",它自己就是完整的,不需要依附于谁。

👶 Element(元素)—— 块的组成部分

Element 是 Block 的子部件,离开了 Block 就没有意义。命名时用双下划线 __ 连接 Block 和 Element。

.menu__item { }
.card__title { }
.button__icon { }
.search-form__input { }

类比:menu__item 就是"菜单里的某一项",它生来就属于 menu,单独拎出来没人知道它是干嘛的。

🎨 Modifier(修饰符)—— 状态或变体

Modifier 用来描述 Block 或 Element 的不同状态、外观或变体。命名时用双连字符 -- 连接。

.button--primary { }
.button--disabled { }
.menu__item--active { }
.card--dark { }

类比:button--disabled 就是"那个被禁用的按钮",它还是按钮,只是状态不一样。


完整公式一览

.block { }
.block__element { }
.block--modifier { }
.block__element--modifier { }

记住这个公式,走遍天下都不怕。


实战演练:一个卡片组件

来看一个完整的例子:

<div class="card card--featured">
  <h2 class="card__title">精选商品</h2>
  <p class="card__description">这是一段商品描述。</p>
  <button class="card__button card__button--primary">立即购买</button>
</div>
/* Block */
.card {
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

/* Block Modifier */
.card--featured {
  border-color: #ff6b6b;
  box-shadow: 0 4px 12px rgba(255, 107, 107, 0.2);
}

/* Elements */
.card__title {
  font-size: 18px;
  margin-bottom: 8px;
}

.card__description {
  font-size: 14px;
  color: #666;
}

.card__button {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

/* Element Modifier */
.card__button--primary {
  background-color: #ff6b6b;
  color: white;
}

看,光看类名你就能知道:

  • card 是主体组件
  • card__title 是卡片里的标题
  • card--featured 是"精选版"卡片
  • card__button--primary 是卡片里那个主色调的按钮

类名自己会说话,不需要注释。


为什么 BEM 这么香?

优点说明
避免样式冲突每个类名都有唯一"户口",不会互相覆盖
自文档化看类名就知道结构和关系,新人也能秒懂
高复用性Block 独立存在,随便拖到哪个页面都能用
团队协作友好统一规则,不用猜别人的命名习惯
低特异性全是单层类名选择器,没有深层嵌套,性能好、易覆盖

一些最佳实践

  1. 全小写 + 连字符分隔单词:search-form ✅,searchForm ❌
  2. 元素不再嵌套命名:不要写 card__body__text,直接 card__text 就好
  3. 修饰符不能单独使用:card--dark 必须和 card 一起出现在 HTML 中
  4. 避免深层 CSS 嵌套:BEM 鼓励用类名直接定位,而不是 .card .body .text 这种选择器
  5. 配合预处理器更舒服:用 Sass 的 & 可以少写很多重复前缀
.card {
  padding: 20px;

  &__title {
    font-size: 18px;
  }

  &__button {
    padding: 8px 16px;

    &--primary {
      background: #ff6b6b;
    }
  }
}

BEM 的"小缺点"

当然,BEM 也不是完美的:

  • 类名偏长:navigation-menu__item--active 写起来确实有点累
  • HTML 略显冗余:一个元素可能要挂多个类名
  • 不是银弹:对于超小型项目,可能有点"杀鸡用牛刀"

但总体来说,在团队协作和中大型项目中,BEM 带来的秩序感远远超过它带来的"打字成本" 。


写在最后

BEM 本质上是一种约定。它不强制你做什么,只是告诉你:如果大家都能遵守同一套命名规则,CSS 的世界就会和平很多。

下次当你准备写一个 .btn 的时候,不妨想一想——它属于哪个 Block?它有没有特殊的 Modifier?想清楚这些,你的 CSS 代码就会从"一盘散沙"变成"训练有素的军队"。

命名是编程中最难的两件事之一,BEM 至少帮我们解决了一半。😉