BEM 是一种前端项目开发的方法论,由 Yandex 公司提出。
BEM 的名称来源于该方法学的三个组成部分的英文首字母,分别是块(Block)、元素(Element)和修饰符(Modifier)。
这里先推荐一篇关于使用 BEM 的组件命令规范的示例文章:bem naming cheat sheet by 9elements。
![](https://i-blog.csdnimg.cn/blog_migrate/9de01a9fb798239caab0f66adf8e3200.png)
其中介绍了包括:面包屑、按钮、卡片、列表、导航、布局、表单控件等一些组件的结构、命令示例。
什么是 CSS BEM?
BEM(Block Element Modifier,块元素修饰符)是 CSS 类的命名约定,旨在通过定义命名空间来解决范围问题来使 CSS 更具可维护性。
它原则上建议为独立的 CSS 类命名,并且在需要层级关系时,将关系也体现在命名中,这自然会使选择器高效且易于覆盖。
block(块)是一个独立的组件,可在项目中重复使用,并充当子组件(元素)的 "命名空间"。
当 block(块)或 element(元素)处于特定状态或结构或样式不同时,将 modifier(修饰符)用作标志。
BEM 命名约定
-
block
代表了更高级别的抽象或组件。 -
block__element
代表.block
的后代,用于形成一个完整的 .block 的整体。 -
block--modifier
代表.block
的不同状态或不同版本。
.block {}
.block__element {}
.block--modifier {}
示例
- BEM 实体名称全部是小写字母或数字。名称中的不同单词用单个连字符(
-
)分隔。 - BEM 元素名称和块名称之间通过两个下划线(
__
)分隔。 - 布尔修饰符和其所修饰的实体名称之间通过两个连字符(
--
)来分隔。不使用名值对修饰符。
<ul class="menu">
<li class="menu__item menu__item--selected">Item 1</li>
<li class="menu__item">Item 2</li>
<li class="menu__item">Item 3</li>
</ul>
CSS 如下:
.menu {
list-style: none;
}
.menu__item {
font-weight: bold;
}
.menu__item--selected {
color: plum;
}
分析
.menu
封装一个独立的实体,它本身是有意义的。虽然块可以嵌套并相互交互,但在语义上它们是相等的;没有优先级或等级制度。.menu__item
块的一部分,没有独立的意义。任何元素在语义上都与其块相关联。.menu__item--selected
块或元素上的修饰符。使用它们来改变外观、行为或状态。
BEM 命名规范带来的好处
BEM 的优点在于所产生的 CSS 类名都只使用一个类别选择器,可以避免传统做法中由于多个类别选择器嵌套带来的复杂的属性级联问题。
换句话说,其所有样式规则的特异性(specificity)都是相同的,也就不存在复杂的优先级问题,简化了层叠规则。如果你还不是很了解特异性的话,可以查阅之前写的一篇 CSS 继承、级联和特异性。
细分后,可以从模块化、可重用性、结构三部分进行理解:
模块化:块样式从不依赖于页面上的其他元素,因此您将永远不会遇到级联带来的问题。
可重用性:以不同的方式构成独立的块,并以智能方式对其进行重用,从而减少了必须维护的 CSS 代码量。
结构:BEM 方法为您的 CSS 代码提供了坚实的结构,使结构保持简单易懂。
其他的一些命名规范
除了 BEM 以外,还有其他一些常用命名规范如:OOCSS、SMACSS 等。
OOCSS
OOCSS 表示的是面向对象 CSS(Object Oriented CSS),是一种把面向对象方法学应用到 CSS 代码组织和管理中的实践
OOCSS 有两个重要的原则
第一个原则是把结构和外观分开。
第二个原则是把容器和内容分开。
SMACSS
SMACSS 表示的是可扩展和模块化 CSS(Scalable and Modular Architecture for CSS)。
SMACSS 把 CSS 样式规则分成若干个不同的类别:
基础:该类别中包含的是默认的 CSS 样式。作为其他样式的基础。
布局:该类别中包含与页面布局相关的 CSS 样式,用来进行模块的排列。
模块:该类别中包含的是可复用的模块的 CSS 样式。
状态:该类别中的 CSS 样式用来描述布局和模块在不同状态下的外观。比如在不同的屏幕尺寸下,布局会发生变化。标签式模块的每个标签页可以有显示或隐藏的状态。
主题:该类别和状态类似,只不过是用来改变布局和模块的视觉效果。