css class names之BEM命名法

168 阅读4分钟

什么是BEM

BEM是非常受欢迎的一个css class names的命名惯例。BEM最基本的概念是非常简单易懂的,但是对于BEM的新手他们还是会出现普通的错误,所以通过下面各种案例来解释。

BEM(Block(容器)-Element(元素)-Modifier(修饰符))它收到广泛的推崇,并且它对于写出更容易阅读、理解和衡量的css是非常有帮助的。

为什么用BEM

BEM命名提供了三个特别的优势

  1. 它传达了目的和功能。
  2. 它传达了组件的结构。
  3. 它设置了一致的相当低的样式选择器的特殊性。

它是如何工作的

它包括三个部分

  1. Block:最外边的父元素的组件部分被定义为block
  2. Element:向里面的一个或多个children组件部分叫做elements。
  3. Modifier:通过Modifier来表示任何一个block或元素有一个标志性的改变。

其用法如下:

[block]__[element]--[modifier]

详细案例

组成没有Elements或Modifiers

简单的组件仅仅只是用单个的元素并且只有一个class,这个class将成为block

<button class=”btn”></button>
<style>
 .btn {} 
</style>

组成只有一个Modifier

一个组件只有一个变化。这个变化应该被用于modifier(修饰性)class。比如下面这个button元素有一个颜色的变化。

<button class="btn btn--secondary"></button>

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

不要独自设置modifier class。这个modifier class是为了记录其某个变换的,而不是代替最基本的class。

比如下面这个做法就是不推荐

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

只有Elements的组件

更加复杂的thml组成会有很多的子元素。每一个子元素都需要命名一个class来给它添加样式。

之前说过,BEM优势之一是保持一个很低和一致的特殊性。不要忽略子元素的类名。否则它会迫使你使用一个元素选择器来给这些元素(可以看下面的imgfigcaption元素)添加样式,那么会增加你的样式特殊性。

不用这些类名可能更加的言简意赅,但是在将来会增加一连串冲突的风险。

BEM目的之一就是用一个类名作为更好的选择器。

<!-- 推荐写法 -->
<figure class="photo"> 
 <img class="photo__img" src="me.jpg"> 
 <figcaption class="photo__caption">Look at me</figcaption> 
</figure> 
<style> 
 .photo { } /* Specificity of 10 */ 
 .photo__img { } /* Specificity of 10 */
 .photo__caption { } /* Specificity of 10 */ 
</style>
<!-- 不推荐的写法 --> 
<figure class="photo"> 
 <img src="me.jpg"> 
 <figcaption>Look at me!</figcaption> 
</figure> 
<style> 
 .photo { } /* Specificity of 10 */ 
 .photo img { } /* Specificity of 11 */ 
 .photo figcaption { } /* Specificity of 11 */ 
</style>

如果你的组件嵌套了多个深层次的子元素,不要试着用紧接着的上一个元素的类名。BEM不是为了创造更深的结构。
一个BEM类名代表这个组件的子元素只包含最基本的或block名和一个元素名。
在下面的例子中,photo__caption__quote在BEM中是不准确的写法,而photo__quote是更合适的写法。

<!-- 推荐写法 --> 
<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"> 
<!-- never include more than one child element in a class name --> Look at me! 
  </blockquote>
 </figcaption> 
</figure> 
<style> 
 .photo { } 
 .photo__img { } 
 .photo__caption { } 
 .photo__caption__quote { } 
</style>

只用Element和Modifier

在一些情况中,你想要在这个组件中的一个元素有变化,可以给这个元素加上一个修饰来代替这个组件。

<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 {
      /* incremental style changes */
    }

    .photo__caption--large {
      /* incremental style changes */
    }
  </style>

基于祖先元素修饰符给元素添加样式

如果你发现你的多个子元素都有相同的修饰,那么可以给祖先元素添加修饰符,然后给每一个子元素添加样式。虽然这样做,会增加你的样式的特殊性,但是会让你的组件写法更简单。

<!-- 推荐写法 -->
  <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命名故意使用双下划线和双连字符来代替分隔符Block-Element-Modifier。原因是为了单个的连字符能被作为单词分隔符来使用。类名应该容易被读懂,所以缩略是不值得被推崇的,除非这个缩略是大家普遍认识的。

<!-- 推荐做法 -->
<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>
<!-- 不推荐写法 -->
// These class names are harder to read
<div class="somethesis somethesis--fastread">
  <div class="somethesis__someelement"></div>
</div>

<style>
  .somethesis {}

  .somethesis--fastread {}

  .somethesis__someelement {}
</style>

BEM使你开心

如果你之前没用过BEM,现在推荐可以在你的下一个项目尝试使用它。也许一开始会觉得和你之前的写法不同,但是我确信你将会你会看到它在你的项目里会提供或大或小的优势。

文章翻译自BEM by Example