譯文: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去拉平你的特異性圖。

相關文章
相關標籤/搜索