CSS BEM 命名规范
2025/11/4大约 4 分钟
基本介绍
BEM(Block Element Modifier)是一种前端 CSS 命名方法论,核心目标是通过 “统一命名规则” 解决 CSS 命名混乱、作用域冲突、复用性差、维护困难等问题。
核心概念
BEM 的命名格式固定为:块__元素--修饰符(双下划线分隔元素,双连字符分隔修饰符),三者各司其职,不可混淆。
Block(块)
- 定义:页面中独立存在、具有完整功能的 “最小单元”,可单独复用,不依赖其他组件。
 - 特点: 
- 语义独立:名称能明确表达功能(如 
header、button、card),不包含样式描述(避免red-button、big-card)。 - 可复用:可在页面多个位置调用(如 
button块可在表单、弹窗中重复使用)。 - 不影响外部:内部样式不依赖外部环境,外部样式也不会穿透到块内部。
 
 - 语义独立:名称能明确表达功能(如 
 
示例
<!-- 正确:语义化的块(导航、按钮、卡片) -->
<nav class="nav"></nav>
<button class="button"></button>
<div class="card"></div>
<!-- 错误:包含样式描述(red)或依赖外部(header-nav) -->
<div class="red-card"></div>
<div class="header-nav"></div>Element(元素)
- 定义:块内部的 “子节点”,依赖块存在,无法单独复用(脱离块后无意义)。
 - 特点: 
- 从属关系:名称需体现与块的关联(如 
nav__item是nav块的子项)。 - 不可独立:不能脱离块使用(如单独写 
<li class="__item">无效)。 - 不嵌套命名:元素不能包含其他元素(避免 
nav__item__link,需简化为nav__link)。 
 - 从属关系:名称需体现与块的关联(如 
 
示例
<!-- 正确:块 + 元素(nav 的子项、标题、链接) -->
<nav class="nav">
  <ul class="nav__list">
    <li class="nav__item">
      <a class="nav__link" href="#">首页</a>
    </li>
  </ul>
</nav>
<!-- 错误:元素嵌套命名、脱离块使用 -->
<!-- 嵌套错误 -->
<li class="nav__item__link"></li>
<!-- 脱离块 -->
<a class="__link"></a>Modifier(修饰符)
- 定义:用于修改块或元素的 “样式、状态、行为”,不单独使用,需附加在块或元素上。
 - 特点: 
- 描述性:名称体现 “变化”(如 
disabled、large、active)。 - 附加性:必须和块 / 元素一起使用(如 
button--disabled不能单独写--disabled)。 - 可组合:多个修饰符可共存(如 
button--large--primary)。 
 - 描述性:名称体现 “变化”(如 
 - 分类: 
- 状态修饰符:描述临时状态(
active、disabled、hidden)。 - 变体修饰符:描述固定样式变体(
large、primary、round)。 
 - 状态修饰符:描述临时状态(
 
示例
<!-- 正确:块 + 修饰符、块 + 元素 + 修饰符 -->
<button class="button button--primary button--large">主要按钮</button>
<nav class="nav">
  <a class="nav__link nav__link--active" href="#">当前页</a>
</nav>
<!-- 错误:单独使用修饰符、修饰符描述不清晰 -->
<!-- 单独使用 -->
<button class="--primary"></button>
<!-- 样式描述(建议用主题类如 --theme-danger) -->
<div class="card card--red"></div>命名规则
- 分隔符固定: 
- 块与元素:双下划线 
__(禁止单下划线_)。 - 块 / 元素与修饰符:双连字符 
--(禁止单连字符-)。 - 单词间:单连字符 
-(如nav__user-link,禁止下划线或驼峰nav__userLink)。 
 - 块与元素:双下划线 
 - 命名小写:所有名称统一小写(避免 
Button--Primary)。 - 不嵌套元素:元素是块的直接 “语义组成”,不是 DOM 结构的直接子节点(如 DOM 中 
ul > li > a,BEM 命名为nav__list、nav__item、nav__link,而非nav__list__item)。 - 修饰符不单独使用:必须附加在对应的块或元素上(如 
button--disabled不能脱离button块)。 
示例
基础按钮(块 + 修饰符)
HTML
<!-- 普通按钮、主要按钮、禁用按钮 -->
<button class="button">默认按钮</button>
<button class="button button--primary">主要按钮</button>
<button class="button button--disabled" disabled>禁用按钮</button>CSS
/* 块:基础样式(所有按钮共用) */
.button {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
/* 修饰符:变体样式(覆盖/扩展基础样式) */
.button--primary {
  background-color: #1890ff;
  color: #fff;
}
/* 修饰符:状态样式 */
.button--disabled {
  background-color: #f5f5f5;
  color: #ccc;
  cursor: not-allowed;
}卡片组件(块 + 元素 + 修饰符)
HTML
<div class="card card--shadow">
  <div class="card__header">
    <h3 class="card__title card__title--large">卡片标题</h3>
  </div>
  <div class="card__content">卡片内容描述</div>
  <div class="card__footer">
    <button class="button button--primary card__button">操作按钮</button>
  </div>
</div>CSS
/* 块:卡片基础样式 */
.card {
  width: 300px;
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 16px;
  margin: 8px;
}
/* 块修饰符:带阴影的变体 */
.card--shadow {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* 元素:卡片内部组成部分 */
.card__header {
  margin-bottom: 12px;
}
.card__title {
  font-size: 16px;
  font-weight: 600;
}
/* 元素修饰符:大标题变体 */
.card__title--large {
  font-size: 18px;
}
.card__content {
  color: #666;
  line-height: 1.5;
  margin-bottom: 16px;
}
.card__button {
  margin-left: auto;
  display: block;
}导航栏(复杂块 + 多级元素)
HTML
<nav class="nav nav--dark">
  <div class="nav__logo">
    <img src="logo.png" alt="logo" class="nav__logo-img">
  </div>
  <ul class="nav__menu">
    <li class="nav__menu-item">
      <a href="#" class="nav__menu-link nav__menu-link--active">首页</a>
    </li>
    <li class="nav__menu-item">
      <a href="#" class="nav__menu-link">产品</a>
    </li>
  </ul>
  <button class="nav__search-btn">搜索</button>
</nav>CSS
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 60px;
  padding: 0 20px;
  background-color: #fff;
}
/* 块修饰符:深色主题 */
.nav--dark {
  background-color: #1f2937;
  color: #fff;
}
.nav__logo {
  display: flex;
  align-items: center;
}
.nav__logo-img {
  height: 40px;
}
.nav__menu {
  display: flex;
  list-style: none;
  gap: 24px;
}
.nav__menu-link {
  color: inherit;
  text-decoration: none;
}
/* 元素修饰符:激活状态 */
.nav__menu-link--active {
  color: #1890ff;
  font-weight: 600;
  border-bottom: 2px solid #1890ff;
}BEM 扩展
与 CSS 预处理器(Sass/Less)结合
.card {
  padding: 16px;
  
  // 元素:嵌套在块内,无需重复写 card__
  &__header {
    margin-bottom: 12px;
  }
  
  // 修饰符:嵌套在块内,无需重复写 card--
  &--shadow {
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  }
  
  // 元素+修饰符
  &__title {
    font-size: 16px;
    
    &--large {
      font-size: 18px;
    }
  }
}更新日志
2025/11/4 05:39
查看所有更新日志
133be-于
