lbp的blog

纸上得来终觉浅,绝知此事要躬行

0%

CSS的BEM规范

css是用来服务于html,给html增加样式。一般情况下我们使用外部样式表,在html中定义类名,使用选择器进行样式绑定。
css样式是没有作用域而言的,最终生效的样式效果取决于权重。
为了样式的健壮性,防止样式冲突。
一般而言我们使用scss或者less等预处理器,嵌套书写样式表。
这种形式,不便于项目的维护。当需求进行变更时,css的查找修改需查看一层层的嵌套结构。
理想状态下,我们开发一套组件可以中,我们可以随意为其中的元素命名,没有复杂的嵌套,不用担心是否与组件以外的元素发生冲突
bem解决这一问题的思路是:按照组件名是唯一性的思路,在对元素进行命名是包含组件名来保证组件内部的样式不会和外部冲突。
约定形式如下:
block__element--modifier

block:组件最外层的祖先元素定义为块
element:组件内部的后代元素,可能是一个或者是多个。不需要考虑层级关系
modifier:块或者元素的一个变体
以下使用几个例子来更直观的认知BEM

例子

组件

如果是一个简单的组件就用一个块来表示

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
26
27
28
29
30
31
32
33
34
<button class="btn"></button>

<style>
.btn {}
</style>
```
# 带修饰符的组件

**组件可能会有变体,使用修饰符来实现**
```html
<!-- 这样写 -->
<button class="btn btn--secondary"></button>

<style>
.btn {
display: inline-block;
color: blue;
}
.btn--secondary {
color: green;
}
</style>
```
**修饰符是配合基础类使用的,不能够单独使用**
```html
<!-- 不要这样写 -->
<button class="btn--secondary"></button>

<style>
.btn--secondary {
display: inline-block;
color: green;
}
</style>

带元素的组件

如果组件包含后代元素,每一个元素都应该有一个名字。

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
26
27
28
29
30
31
32
33
34
<!-- 这样写 -->
<figure class="photo">
<img class="photo__img" src="me.jpg">
<figcaption class="photo__caption">
<blockquote class="photo__quote">
Look at me!
</blockquote>
</figcaption>
</figure>

<style>
.photo { }
.photo__img { }
.photo__caption { }
.photo__quote { }
</style>


<!-- 不要这样写 -->
<figure class="photo">
<img class="photo__img" src="me.jpg">
<figcaption class="photo__caption">
<blockquote class="photo__caption__quote"> <!-- 类名中出现的后代元素不能多于一个 -->
Look at me!
</blockquote>
</figcaption>
</figure>

<style>
.photo { }
.photo__img { }
.photo__caption { }
.photo__caption__quote { }
</style>

从上面可以看出,不需要在类名中表现出来每一层,bem不体现结构的关系。

带修饰符的元素

你可能希望修改组件中的某个元素的样式。这时候,应该给元素而不是组件添加修饰符。

1
2
3
4
5
6
7
8
9
10
11
12
13
<figure class="photo">
<img class="photo__img photo__img--framed" src="me.jpg">
<figcaption class="photo__caption photo__caption--large">Look at me!</figcaption>
</figure>

<style>
.photo__img--framed {
/* 增量样式修改 */
}
.photo__caption--large {
/* 增量样式修改 */
}
</style>

基于组件修饰符书写样式

如果你发现自己总是以相同的方式修改某个组件里的多个元素,那么可以考虑将修饰符添加到组件的基类名上,并根据这个修饰符的含义,调整每个后代元素的样式。这种方式会增加选择器权重,但让修改组件样式变得更简单了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 这样写 -->
<figure class="photo photo--highlighted">
<img class="photo__img" src="me.jpg">
<figcaption class="photo__caption">Look at me!</figcaption>
</figure>

<style>
.photo--highlighted .photo__img { }
.photo--highlighted .photo__caption { }
</style>

<!-- 不要这样写 -->
<figure class="photo">
<img class="photo__img photo__img--highlighted" src="me.jpg">
<figcaption class="photo__caption photo__caption--highlighted">Look at me!</figcaption>
</figure>

<style>
.photo__img--highlighted { }
.photo__caption--highlighted { }
</style>

多词名称

BEM 名称故意使用双下划线和双连字符,来分隔块-元素-修饰符。如果使用的名称中包含多个单词,那么就可以使用一个连字符连接这多个单词。这样的类名更加易读,同时,应该尽量避免使用缩写,除非这个缩写是大家普遍知道的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 这样写 -->
<div class="some-thesis some-thesis--fast-read">
<div class="some-thesis__some-element"></div>
</div>

<style>
.some-thesis { }
.some-thesis--fast-read { }
.some-thesis__some-element { }
</style>

<!-- 不要这样写
名称读起来很费劲
-->
<div class="somethesis somethesis--fastread">
<div class="somethesis__someelement"></div>
</div>

<style>
.somethesis { }
.somethesis--fastread { }
.somethesis__someelement { }
</style>

TODO 主流框架中的bem分析

个人思考

不同页面下,存在相同名称的组件,如何处理
css和html是嵌套使用,但是bem不能够体现嵌套结构,表达不清晰

参考

BEM by Example
bemcss