CSS命名规范---BEM规范

CSS命名规范---BEM规范

二月 13, 2019

最近没事在看Bootstrap v4的源码,感觉它的命名很有意思,于是网上搜索了一番,发现了一个新东西:BEM。这是个什么东西呢,引用官网的描述:

BEM (Block, Element, Modifier) is a component-based approach to web development. The idea behind it is to divide the user interface into independent blocks. This makes interface development easy and fast even with a complex UI, and it allows reuse of existing code without copying and pasting.

简而言之,就是更好的复用。BEM是block(块),element(元素)和modifier(修饰符)三个单词的首字母,是由Yandex团队提出的一种前端命名方法论。它的命名约定更加严格,对于其他开发者来说也更加透明且更有意义。

释义

  • Block

    块,代表了页面上一个可以复用的组件,意思就是你要描述一个什么东西,比如菜单,按钮之类的,不包含状态,是更高级别的一种抽象。

  • Element

    元素,一个块中的多个元素后代,比如我有一个form块,里边包含了input,button之类的,那么这些就是块的元素,元素集合组成块。

  • Modifier

    修饰符,它描述的是appearance(比如size,theme),state(比如禁用),behavior(比如定位),可以修饰块,也可以修饰元素。

命名约定

  • 官方
1
2
3
4
5
6
7
8
// 单独一个块
.block{}
// 块 + 元素
.block__element{}
// 块 + 修饰符
.block_modifier
// 块 + 元素 + 修饰符
.block__element_modifier
1
2
3
4
5
6
7
8
// 单独一个块
.block{}
// 块 + 元素
.block__element{}
// 块 + 修饰符
.block--modifier
// 块 + 元素 + 修饰符
.block__element--modifier

两者不同的地方就在于modifier的连接,官方是用_,而后者采用–,看起来更有意义。这与传统的全部-连接更具有视觉上的分辨,让开发者可以更容易的看到dom的结构组成。虽然第一眼看上去很怪,但是更具有维护意义。

示例

举个最简单的例子,页面顶部,这可以看成页面的一个组件,在BEM规范中就是一个块,我们可以封装一下,如果其他部分要用到类似的顶部结构,可以直接拿来使用。我们假想顶部栏中有以下4个东西:

  1. logo
  2. 名字
  3. 一个搜索框(搜索菜单栏用的)
  4. 用户头像(可以进入用户信息界面)

接下来我们用BEM规范来构建一下css:

首先,这是一个块,我们起名为header,块中有4个元素,就是我们上说的4个,同时我们给顶部设置2套不同颜色的主题,input框加一个激活样式,最后生成的结构如下:

1
2
3
4
5
6
<div class="header header--black">
<div class="header__logo"></div>
<div class="header__text"></div>
<div class="header__input header__input--focus"></div>
<div class="header__img"></div>
</div>

当然,这只是最简单的一种形式,我们完全可以块嵌套,元素嵌套组成更复杂的BEM Css结构。这其中有一点特殊的要注意,就是元素之间的嵌套,多层嵌套不要把上一层的class名字添加到下一层的类名前,引用官方的一个案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!--
Correct. The structure of the full element name follows the pattern:
`block-name__element-name`
-->
<form class="search-form">
<div class="search-form__content">
<input class="search-form__input">

<button class="search-form__button">Search</button>
</div>
</form>

<!--
Incorrect. The structure of the full element name doesn't follow the pattern:
`block-name__element-name`
-->
<form class="search-form">
<div class="search-form__content">
<!-- Recommended: `search-form__input` or `search-form__content-input` -->
<input class="search-form__content__input">

<!-- Recommended: `search-form__button` or `search-form__content-button` -->
<button class="search-form__content__button">Search</button>
</div>
</form>

上面写的很清楚,嵌套之内的元素也是块的组成部分,我们应该按照block__element的形式进行命名,而不是根据父级元素的命名走。

不论是传统的-命名,还是BEM规范,它们都是为了css的简化理解和维护,而BEM规范在这点上更有说服力,这对于前端开发者来说是一个相当有价值的规范,极力推荐大家使用。