一、BEM基础介绍

  1. 定义:BEM(Block Element Modifier)是由Yandex团队提出的前端CSS类名命名方法论,通过块、元素、修饰符三部分构建清晰的组件结构,是现代前端开发中广泛采用的CSS模块化方案。

  2. 核心价值:提升CSS代码可维护性、避免样式冲突、支持组件复用,尤其适配中大型前端项目。

  3. 基础标识:双下划线__连接块与元素,双连字符--表示修饰符,示例:.menu__item--active

二、BEM核心概念

组成部分 描述 示例 核心作用
Block(块) 独立且有意义的组件 .header.menu.card 表示可独立复用的基础组件
Element(元素) 块的组成部分 .menu__item.card__title 块的从属部分,无法独立存在
Modifier(修饰符) 块/元素的状态/变体 .menu--vertical.card__button--disabled 表示组件的不同状态或样式变体

三、命名语法规则

1. 基本语法结构

1
2
3
4
5
6
7
8
9

/* 块 */
.block {}
/* 块-元素 */
.block__element {}
/* 块-修饰符 */
.block--modifier {}
/* 块-元素-修饰符 */
.block__element--modifier {}

2. 分隔符说明

  • __(双下划线):仅用于连接元素,无其他用途;

  • --(双连字符):仅用于连接块/元素修饰符

  • -(单连字符):可选,用于多单词名称的连接,示例:.search-form.nav__submenu

四、BEM命名核心原则

1. 块(Block)的独立性

  • 可在页面任意位置复用,不依赖其他元素/块;

  • 块本身不设置外边距(margin),由其容器控制位置。

2. 元素(Element)的从属性

  • 元素名称必须归属某个块,格式固定为block__element

  • 同一块内的不同元素可嵌套,无需考虑嵌套层级。

3. 修饰符(Modifier)的可选性

  • 修饰符不能单独使用,必须与块/元素类名配合;

  • 同一元素可添加多个修饰符,实现多状态组合;

  • 格式为block--modifier(块修饰)或block__element--modifier(元素修饰)。

五、完整代码示例

1. HTML结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14

<!-- 搜索组件(块) -->
<form class="search-form">
<input class="search-form__input" type="text" placeholder="搜索...">
<button class="search-form__button search-form__button--primary" type="submit">搜索</button>
<button class="search-form__button search-form__button--secondary" type="reset">重置</button>
</form>
<!-- 卡片组件(块+修饰符) -->
<div class="card card--featured">
<img class="card__image" src="image.jpg" alt="示例">
<h3 class="card__title">特荐产品</h3>
<p class="card__description card__description--truncated">这是一个很长的描述文本,会被截断显示...</p>
<button class="card__button">了解更多</button>
</div>

2. 对应CSS样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

/* 搜索表单块 */
.search-form { display: flex; gap: 10px; padding: 20px; background: #f5f5f5; }
/* 搜索表单元素 */
.search-form__input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
.search-form__button { padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
/* 搜索表单元素修饰符 */
.search-form__button--primary { background-color: #007bff; color: white; }
.search-form__button--secondary { background-color: #6c757d; color: white; }

/* 卡片块 */
.card { border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; max-width: 300px; }
/* 卡片块修饰符 */
.card--featured { border-color: #007bff; box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2); }
/* 卡片元素 */
.card__title { font-size: 1.5rem; margin-bottom: 10px; color: #333; }
.card__description { color: #666; line-height: 1.5; }
.card__button { margin-top: 15px; padding: 8px 16px; background-color: #28a745; color: white; border: none; border-radius: 4px; }
/* 卡片元素修饰符 */
.card__description--truncated { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

六、实际项目应用场景

1. 导航菜单

1
2
3
4
5
6
7
8
9
10

<nav class="nav">
<ul class="nav__list">
<li class="nav__item"><a class="nav__link nav__link--active" href="#">首页</a></li>
<li class="nav__item nav__item--dropdown">
<a class="nav__link" href="#">服务</a>
<ul class="nav__submenu"><li class="nav__subitem"><a class="nav__sublink" href="#">设计</a></li></ul>
</li>
</ul>
</nav>

2. 表单控件(带错误状态)

1
2
3
4
5
6

<div class="form-field">
<label class="form-field__label" for="email">邮箱</label>
<input class="form-field__input form-field__input--error" id="email" type="email">
<div class="form-field__error-message">请输入有效的邮箱地址</div>
</div>

3. 响应式修饰符

1
2
3
4
5
6

/* 移动端隐藏,平板及以上显示 */
.menu__item--hidden-mobile { display: none; }
@media (min-width: 768px) {
.menu__item--hidden-mobile { display: block; }
}

七、BEM的常见变体

1. BEM + Sass/SCSS(推荐)

利用Sass嵌套语法简化书写,通过&引用父选择器,保持代码层级清晰:

1
2
3
4
5
6
7
8
9
10
11
12
13

.menu {
display: flex;
&__list { list-style: none; }
&__item {
margin-right: 20px;
&--active { font-weight: bold; }
}
&__link {
color: #333;
&:hover { color: #007bff; }
}
}

2. 命名空间变体

为类名添加前缀,区分组件类型,提升可读性:

1
2
3
4
5

.c-card {} /* c-:通用组件(Component) */
.l-header {} /* l-:布局组件(Layout) */
.u-text-center {} /* u-:工具类(Utility) */
.js-modal {} /* js-:JavaScript钩子(仅用于JS操作,不写样式) */

3. 更严格的BEM

避免元素嵌套式命名,采用扁平结构,防止类名过长:

1
2
3
4
5

/* 推荐 */
.block__element2-child {}
/* 禁止 */
.block__element2__child {}

八、BEM的优缺点

优点

  1. 结构清晰:直观体现HTML与CSS的对应关系,易读易维护;

  2. 避免冲突:每个类名都有独立命名空间,解决样式污染问题;

  3. 减少嵌套:仅需一层选择器,降低CSS选择器特异性,提升渲染性能;

  4. 便于协作:统一命名规范,减少团队沟通成本;

  5. 模块化:组件可独立开发、测试和复用,适配工程化开发。

缺点

  • 类名长度偏长,纯手写时稍显繁琐(可通过Sass/PostCSS工具优化)。

九、使用注意事项

  1. 避免过度使用:简单项目/小组件无需完整BEM,避免冗余;

  2. 坚持语义化命名:根据功能命名,而非样式,示例:用.box__status--error代替.box__red

  3. 控制类名长度:若类名过长,需重新设计组件结构,拆分独立块;

  4. 兼容其他方案:可与CSS-in-JS、Bootstrap等框架结合使用,用于自定义组件;

  5. 修饰符必配合基础类:不可单独写.button--primary,需与.button配合。

十、BEM与其他CSS命名方法对比

方法 核心理念 优点 缺点
BEM 块-元素-修饰符 结构清晰,避免冲突,易协作 类名较长
OOCSS 对象化CSS 高度复用,分离结构与皮肤 需抽象思维,对初学者不友好
SMACSS 可扩展模块化架构 分类清晰,适配大型项目 规则较多,配置繁琐
ITCSS 倒三角CSS 层次分明,精准控制选择器特异性 学习曲线较陡
Atomic CSS 原子化CSS 极致复用,样式文件体积小 类名无语义,可读性差

十一、学习与实践建议

  1. 从简入手:先在单个小组件(如按钮、卡片)上实践,再逐步推广到整个项目;

  2. 团队统一规范:约定分隔符、命名空间、多单词连接方式,保持项目内一致性;

  3. 结合工具:使用Sass/SCSS嵌套、PostCSS插件简化BEM书写,提升效率;

  4. 文档化:为复杂组件编写BEM结构文档,方便团队查阅和维护;

  5. 灵活适配:根据项目规模调整BEM严格程度,无需生搬硬套规则。