译文:Nesting Your BEM?

原文连接:http://csswizardry.com/2016/11/nesting-your-bem/css

在我开始这篇文章以前,我得说这不是一个建议或者是新的“练习指南”。这只是我本身的一些思想狂潮。sass

我是一个[<cite>BEM</cite>](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/)的拥护和支持者。而且已经持续了不少年。这是有点有趣的期待。固然, 它给我提供了不少的东西:ide

* **软封装** 这有助于减小命名冲突。
* **自定义的CSS** 这帮助我理解DOM节点彼此之间的关系。
* **目标的选择** 这有助于减小子树之间的冲突,而且避免捕获太多的节点。
* **管理方式的特殊性** 这是一个很大的亮点。
* **严格的实现规则** 这可以防止我使用给定上下文之外的classes。ui

除了最后一点只有一半是真的......3d

BEM告诉咱们,一个class, 例如: `.widget__title`, 仅仅只能被用在`.widget`内。 可是这仅仅是经过了协议的规定。开发人员可能会把`.widget_title`放在`.model`以内,而且仍能正常工做。这是由于:ci

* 他们以前没有见过BEM,或者是不知道执行它的方法
* 他们很懒惰,而且发现———即便是不该该,可是他们能够重用`.modal`内的`.widget_title`样式的,而后这样可以提早5分钟完成工做开发

他们可以作到这一点,它也能为他们工做:东西仍旧可以正确显示。不会所以致使额外的错误,由于 BEM 仅仅是一个规定,而且规定须要一致的认同。get

为了规避这一点,咱们能够像下面这样地来写CSS:it

```
.widget { }io

.widget .widget__title { }
```

如今开发者不能在`.modal`内使用`.widget_title`,由于咱们告诉了咱们的CSS:`wideget_title`仅仅在咱们把它放到`.widget`中才能起效。如今咱们开始执行这些事情,它将防止滥用。

这里还有一个问题:嵌套

## CSS中的嵌套


在很长的一段时间内,我曾[<cite>积极主张</cite>](http://cssguidelin.es/#specificity)CSS中的嵌套是一件坏事情,由于:

* 增长了特性 (这些应该始终要管理好);
* 引入了对存储位置的依懒 (不灵活系统的一个标志);
* 减小了可移植性 (这意味着咱们不能随意移动它);
* 增长了脆弱性 (嵌套意味着选择器出错的可能性增长了)。

总之, [<cite>保持你的CSS选择器的简短性</cite>](http://csswizardry.com/2012/05/keep-your-css-selectors-short/).

可是在使用了嵌套BEM的状况中,咱们看到了嵌套给咱们带来了实实在在的好处。可是咱们要如何处理这些缺陷呢?

## 特异性

注意,一般状况下始终保持低特异性是很重要的。这彻底正确,而且这是一个很好的建议。可是,这里和咱们熟知的那些是有一点区别的。人们在说特异性应当在任何状况下都处理好的时候,真正的意思是,咱们应当保持一致性,而且选择器之间的区别很小。

理论上来讲(可是,亲爱的,请不要尝试这样作),一个项目的惟一选择器是ID选择器,这将很好地管理特异性:特异性广泛是高的,但至少全部都符合而且相等。

当咱们在讨论如何处理好一致性的问题时:咱们指的是它的[<meta>特异性图<meta>](http://csswizardry.com/2014/10/the-specificity-graph/)尽量的平缓。

若是咱们观察下面这一系列的CSS组件:

```
.nav-primary { }

.nav-primary__item { }

.nav-primary__link { }

.masthead { }

.masthead__media { }

.masthead__text { }

.masthead__title { }

.sub-content { }

.sub-content__title { }

.sub-content__title--featured { }

.sub-content__img { }
```

…咱们发现,他们每一个class之间有着彻底相同的特异性。这是一个很漂亮的平缓特异性图:

<figure>![Graph showing low and flat specificity](http://p0.qhimg.com/t01298e8f9265d223bb.png)

<figcaption>[<cute>查看大图</cute>](http://csswizardry.com/wp-content/uploads/2016/11/graph-specificity-01.png)</figcaption>

</figure>

一旦咱们像下面这样去嵌套这些classes:

```
.nav-primary { }

.nav-primary .nav-primary__item { }

.nav-primary .nav-primary__link { }

.masthead { }

.masthead .masthead__media { }

.masthead .masthead__text { }

.masthead .masthead__title { }

.sub-content { }

.sub-content .sub-content__title { }

.sub-content .sub-content__title--featured { }

.sub-content .sub-content__img { }
```

…咱们看到的特异性图将会是这样的:

<figure>![Graph showing changes in specificity](http://p0.qhimg.com/t01afba20a956d400fc.png)

<figcaption>[<meta>查看大图</meta>](http://csswizardry.com/wp-content/uploads/2016/11/graph-specificity-02.png)</figcaption>

</figure>

哦,天啊! 峰值(Spikes)! 峰值正是咱们想要避免的,由于他们表明着项目中很是接近的选择器之间的特异性的波动。

这里咱们看了嵌套中特异性致使的一些缺陷(Here we are visualising the specificity downside to nesting.)咱们能避开它吗?怎样作?

## 连接第一个class

若是咱们要连接第一个class (the Block) 到它自身, 像这样:

```
.nav-primary.nav-primary { }

.nav-primary .nav-primary__item { }

.nav-primary .nav-primary__link { }

.masthead.masthead { }

.masthead .masthead__media { }

.masthead .masthead__text { }

.masthead .masthead__title { }

.sub-content.sub-content { }

.sub-content .sub-content__title { }

.sub-content .sub-content__title--featured { }

.sub-content .sub-content__img { }
```

…咱们可使其特异性地匹配全部无反作用的嵌套元素:

* 咱们不须要知道这个Block在DOM中的位置,所以咱们不会依据一些可能更改的位置而去增长它的特异性
* 咱们并无链接到另外一个不一样的或者是特定的元素或者类。这意味着Block类依旧很是轻便。

这种特异性的增长彻底依据它自身,如今咱们看到了这样的特异性图:

<figure>![Graph showing higher but still flat specificity](http://p0.qhimg.com/t01cecef3a98ac52bbf.png)

<figcaption>[<cute>查看大图</cute>](http://csswizardry.com/wp-content/uploads/2016/11/graph-specificity-03.png)</figcaption>

</figure>

比第一张图高,可是仍旧很是平缓。尽管咱们咱们的特异性是两级的高度,它仍旧被很好的掌控:咱们选择器组件没有特殊的权重。

## 用Sass简化

为了使嵌套以及连接更加简化,咱们可使用预处理,在这里是Sass:

咱们应当都熟悉如何在Sass中嵌套常规选择器:

```
.nav-primary {

.nav-primary__item { }

.nav-primary__link { }

}
```

这给咱们带来了,正如咱们所期待的:

```
.nav-primary { }

.nav-primary .nav-primary__item { }

.nav-primary .nav-primary__link { }
```

可是咱们如何快速而且有效地将第一个class连接到他自身?像这样:

```
.nav-primary {

&#{&} { }

.nav-primary__item { }

.nav-primary__link { }

}
```

经过使用 `&#{&}`, 咱们能够将当前的class连接到它自身。这意味着咱们全部Block的样式(在这种状况下, `.nav-primary`) 都在这里:

```
.nav-primary {

&#{&} { /* Block styles */ }

}
```

[<cute>看一个关于Sassmeister的小例子</cute>](http://www.sassmeister.com/gist/a14e5b242ee6b20932dd44df0a3d215c)

## 实际结果

如今,咱们的处境是事实上在强制地使用,而且主动地阻止选择器的起效——若是咱们主动地将它们从DOM中正确的部分移出的话。这能够帮助咱们在其余开发者并不知道BEM如何起效的环境下工做,或者是那些倾向于使劲折腾直到一切看上去正常的人。

咱们也有一个管理全部classes(虽然是增长的)的特异性

### 缺陷

咱们正在增长一些特异性,这一般正是咱们应该永远努力去避免的。

## 用例

若是你想要尝试延伸这种技术,开始以前,这里有必要确认一些关键的用例。第一个展示在我脑中的是 网格系统(grid systems) 一次又一次地,我看见开发者们在`.grid`父类外尝试去使用`.grid__item`类。因此,若是我打算开始使用这种技术的话,我会从这里开始:

```
.grid.grid { }

.grid .grid__item { }
```

## 用仍是不用?

我不是很肯定,正如我在开头说的那样,这不是一项我很是推荐而且致力于推行的技术。我仅仅是想要提出它,给你们做为一个参考,尤为是对那些发现本身正处于一个,其余开发者都在轻易地滥用CSS的环境中的开发者。

可是,我想说的是:若是你已经嵌套了你的BEM,请返回,经过连接你的第一个class去拉平你的特异性图。

相关文章
相关标签/搜索