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

先从一个"惨案"说起

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

你给按钮写了个 .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。

markdown 复制代码
.menu__item { }
.card__title { }
.button__icon { }
.search-form__input { }

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

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

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

lua 复制代码
.button--primary { }
.button--disabled { }
.menu__item--active { }
.card--dark { }

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


完整公式一览

lua 复制代码
.block { }
.block__element { }
.block--modifier { }
.block__element--modifier { }

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


实战演练:一个卡片组件

来看一个完整的例子:

ini 复制代码
<div class="card card--featured">
  <h2 class="card__title">精选商品</h2>
  <p class="card__description">这是一段商品描述。</p>
  <button class="card__button card__button--primary">立即购买</button>
</div>
css 复制代码
/* 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 的 & 可以少写很多重复前缀
css 复制代码
.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 至少帮我们解决了一半。😉

相关推荐
2603_965896621 小时前
CSS BEM 命名规范|组件化样式分层权威指南
前端·javascript·css
deli0071 小时前
中文在网址里为什么变成 E4B8AD?URL 编码 22 组用例实测
前端
羲云1 小时前
MOSS-Image 开源后爆火:5B 生图模型真正值得关注的,是可控排版
前端
BreezeJiang1 小时前
闭包和 useState 是两个知识点?你可能只学了半条作用域链
前端·面试
2601_958352901 小时前
一款模块通吃15类语音产品?AN-93如何实现录音笔、门禁、IPC的快速适配
前端·人工智能·嵌入式硬件·回声消除·降噪处理
子兮曰1 小时前
Bun v1.4.4 实测:2,025 个文件,bun fmt 2.6 秒跑完
前端·后端·bun
Liudef061 小时前
用 DeepSeek Search API 做一个干净的单文件搜索页面(附完整源码)
前端·人工智能·工具·搜索·deepseek
忆挽篱笙歌2 小时前
进程替换函数与shenll命令行解释器
前端·javascript·算法
计算机魔术师2 小时前
砸了2200亿美元还是不够用,AWS说2027年也卖完了
前端