BEM命名实例
BEM (Block-Element-Modifier的缩写)是CSS类名的命名约定标准。它被广泛采用,在编写更容易阅读、理解和扩展的CSS时非常有用。
为什么用BEM命名
BEM命名提供了三个具体的好处:
- 表明目的或者功能
- 表明组件结构
- 为样式选择器提供了低等级的一致性
使用方法
BEM类名最多包括三个部分。
- Block:组件的最外层父元素被定义为块。
- Element:组件内部可能有一个或多个称为元素的子组件。
- Modifier:一个块或元素可以有一个由修饰语表示的变化。
用这三部分就能组成:[block]__[element]--[modifier。 在简短的介绍之后,让我们看一些具体的例子。
例子
没有元素或修饰符的组件
<button class=”btn”></button>
<style>
.btn {}
</style>
有一个修饰符的组件
组件可能有变化。这个变化应该用一个修饰符类来实现。
<!-- DO THIS -->
<button class="btn btn--secondary"></button>
<style>
.btn {
display: inline-block;
color: blue;
}
.btn--secondary {
color: green;
}
</style>
不要单独使用修饰符类。修饰符类用于增加基类,而不是替换基类。
带元素组件
更复杂的组件会有子元素。每个需要样式化的子元素都应该包含一个命名类。
BEM背后的目的之一是保持低特异性和一致性。不要从HTML中的子元素中省略类名。这将迫使您使用具有更高特异性的选择器来对组件内的裸元素进行样式化(参见下面的img和figcaption`` elements )。去掉这些类可能更简洁,但是将来会增加级联问题的风险。BEM的一个目标是让大多数选择器只使用一个类名。
<!-- DO THIS -->
<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>
<!-- DON'T DO THIS -->
<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类名应该只包括基本/块名和一个元素名。在下面的例子中,请注意photo__caption__quote是BEM的不正确用法,而photo__quote更合适。
<!-- DO THIS -->
<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>
<!-- DON'T DO THIS -->
<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>
带修饰符的元素
在某些情况下,您可能希望改变组件中的单个元素。在这些情况下,需要给元素而不是组件添加修饰符。我发现修改元素远没有修改整个组件那么常见和有用。
<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>
基于组件修饰符的元素样式
如果您发现自己总是以相同的方式修改同一个组件的元素,那么可以考虑将修饰符添加到组件的基元素中,并根据该修饰符调整每个子元素的样式。这将增加特异性,但它使修改组件变得更加简单。
<!-- DO THIS -->
<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>
<!-- DON'T DO THIS -->
<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。原因是,单个连字符可以用作单词分隔符。类名应该非常易读,所以缩写并不总是可取的,除非缩写是普遍可识别的。
<!-- DO THIS -->
<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>
<!-- DON'T DO THIS -->
// 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,我强烈建议您在下一个项目中使用它。它可能与您所习惯的有所不同,但我相信您很快就会看到它在大大小小的项目中所提供的好处。并且,希望这些示例将帮助您避免我们大多数人在第一次研究这个古怪的命名约定时所犯的一些常见错误。