CSS BEM 命名规范
2025/11/4大约 5 分钟
基本介绍
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 预处理器
.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;
}
}
}常见class关键词
- 布局类:header, footer, container, main, content, aside, page, section
- 包裹类:wrap, inner
- 区块类:region, block, box
- 结构类:hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span
- 列表类:list, item, field
- 主次类:primary, secondary, sub, minor
- 大小类:s, m, l, xl, large, small
- 状态类:active, current, checked, hover, fail, success, warn, error, on, off
- 导航类:nav, prev, next, breadcrumb, forward, back, indicator, paging, first, last
- 交互类:tips, alert, modal, pop, panel, tabs, accordion, slide, scroll, overlay
- 星级类:rate, star
- 分割类:group, seperate, divider
- 等分类:full, half, third, quarter
- 表格类:table, tr, td, cell, row
- 图片类:img, thumbnail, original, album, gallery
- 语言类:cn, en
- 论坛类:forum, bbs, topic, post
- 方向类:up, down, left, right
- 其他语义类:btn, close, ok, cancel, switch; link, title, info, intro, more, icon; form, label, search, contact, phone, date, email, user; view, loading
更新日志
2025/11/10 01:47
查看所有更新日志
48bf1-于133be-于
